Introduction

In recent decades, Philadelphia has experienced substantial changes in population dynamics, economic fluctuations, and redevelopment pressures. Among these changes, housing values have become a key indicator of the socio-economic conditions within the city’s neighborhoods. Rising housing values typically reflect a higher presence of wealthier residents or a neighborhood undergoing gentrification, while declining housing values often signal increased economic pressure or decline. Therefore, accurately forecasting the median housing values across Philadelphia is crucial for urban planners and policymakers, helping them to proactively address potential risks such as displacement and disinvestment. Supporting Philadelphia’s long-term vision of fostering vibrant, diverse, and resilient communities is also essential.

To better understand the potential factors influencing housing values in Philadelphia, we identify several key variables: educational attainment, vacancy rates, the proportion of single-family homes, and poverty levels. These factors are closely related to housing market trends and provide insights into the neighborhood’s socio-economic status.

Educational attainment is closely linked to the socio-economic characteristics of neighborhoods. Individuals with higher educational attainment typically earn higher incomes and contribute more to local economies. A higher concentration of individuals with advanced educational backgrounds tends to increase the demand for well-designed housing in affluent neighborhoods. With a consistent supply, housing prices and values are likely to rise. Similarly, a high poverty rate also indicates a declining community. Since many residents cannot afford luxury housing, the housing values in those neighborhoods are likely to be Lower.

High vacancy rates often correlate with declining neighborhoods and reduced median house values. Research shows that vacant properties affect multiple facets of community life, such as housing and neighborhood vitality, crime prevention efforts, and the well-being of commercial districts. As a result, areas with numerous vacant housing units typically see diminished median housing values.

The proportion of single-family homes in an area influences housing values. These homes are generally private and comfortable, making them more desirable in many U.S. housing markets. However, they are relatively common in suburban neighborhoods and may suffer from low accessibility and limited infrastructure, which can negatively affect their property values as well.

In this study, we utilize ordinary least squares (OLS) regression to analyze the relationship between these socioeconomic factors and median house values in Philadelphia. By examining these relationships, we aim to identify critical predictors of median housing values throughout Philadelphia and offer insights for decision-makers and community initiatives.

Methods

Data Cleaning

To predict median house values in Philadelphia, we obtained the original dataset from the United States Census data. The dataset represents census block groups from the year 2000 and initially contained 1,816 observations. The key variables included:

  • POLY_ID – Census Block Group ID
  • MEDHVAL – Median value of all owner-occupied housing units
  • PCBACHMORE – Proportion of residents in the block group with at least a bachelor’s degree
  • PCTVACANT – Proportion of housing units that are vacant
  • PCTSINGLES – Percentage of housing units that are detached single-family houses
  • NBELPOV100 – Number of households with incomes below 100% of the poverty level
  • MEDHHINC – Median household income

To refine the dataset for modeling purposes, we applied the following filtering criteria:

  1. Retained block groups with a population greater than 40
  2. Included only block groups that contained housing units
  3. Excluded records where the median house value was below $10,000

Additionally, we removed a specific block group in North Philadelphia that exhibited inconsistencies, with an unusually high median house value (over $800,000) despite a very low median household income (less than $8,000).

After data cleaning, the final dataset contained 1,720 observations.

Exploratory Data Anaylsis

Summary Statistics

We will first examine the summary statistics ( mean and standard deviation (SD)) of key variables in the dataset, including the dependent variables MEDHVAL (Median House Value), and predictors NBELPOV100 (Households Living in Poverty), PCTBACHMOR (% of Individuals with Bachelor’s Degrees or Higher), PCTVACANT(% of Vacant Houses), PCTSINGLES( % of Single House Units).

The mean (\(\bar{X}\)) represents the average value of a variable and is calculated as:

\[ \bar{X} = \frac{1}{n} \sum_{i=1}^{n} X_i \]

where:

  • \(X_i\) represents each individual observation
  • \(n\) is the total number of observations

The mean gives us a single representative value of the dataset. To measure variability, we use the standard deviation (SD), which quantifies how much the values in a dataset deviate from the mean. The formula for the sample standard deviation (\(s\)) is:

\[ s = \sqrt{\frac{1}{n-1} \sum_{i=1}^{n} \left( X_i - \bar{X} \right)^2} \]

where:

  • \(X_i\) represents each individual observation
  • \(\bar{X}\) is the mean of the observations
  • \(n\) is the total number of observations

A larger standard deviation indicates that the data points are more spread out, while a smaller standard deviation suggests that the data points are closer to the mean.

Distributions

We will also examine the histograms and apply log transformations for key variables to assess whether the transformed variables follow a more normal-like distribution.

Histograms provide a visual representation of how a variable’s values are distributed, helping to identify whether the data follows a normal distribution, is right-skewed, or left-skewed. Linear regression model assume that variables are approximately normally distributed.

  • X-axis: The values of the variable (e.g., house prices, income levels).

  • Y-axis: The frequency of observations within each bin.

If the histogram is right-skewed, it suggests that a small number of observations have significantly higher values compared to the rest. For variables following a right-skewed distribution, we will apply a log transformation to these variables to improve normality. Since the log transformation is undefined for zero or negative values, we must first check whether any variable contains zero.

  • If no zeros presents, we apply the standard log transformation:
    \[ X' = \log_{10} (X) \]
  • If zeros present, we adjust by adding 1 before taking the log:
    \[ X' = \log_{10} (X + 1) \]
    This ensures that all values remain positive and avoids undefined values.

By comparing the original histograms with the log-transformed histograms, we will assess whether the transformation improves the suitability of the data for predictive modeling.

Correlations

We will analyze correlations between predictors, to detect potential multicollinearity before proceeding with regression analysis, which can distort model interpretations.

Multicollinearity occurs when predictors are highly correlated, which can lead to unstable regression coefficients. It also inflates standard errors, reducing the statistical significance of predictors, and increases the risk of overfitting, as redundant variables do not contribute new information to the model.

The correlation coefficient \(r\) is calculated as:

\[ r = \frac{\sum_{i=1}^{n} (x_i - \bar{x})(y_i - \bar{y})}{\sqrt{\sum_{i=1}^{n} (x_i - \bar{x})^2 \sum_{i=1}^{n} (y_i - \bar{y})^2}} \] In a more concise way, this above formula is also equivalent to the following:

\[ r = \frac{1}{n-1} \sum_{i=1}^{n} \left( \frac{x_i - \bar{x}}{S_x} \right) \left( \frac{y_i - \bar{y}}{S_y} \right) \] where:
- \(X_i\) and \(Y_i\) are individual data points for variables \(X\) and \(Y\), respectively.
- \(\bar{X}\) and \(\bar{Y}\) are the mean values of \(X\) and \(Y\).
- The numerator represents the covariance between \(X\) and \(Y\), while the denominator normalizes the values.

The correlation coefficient \(r\) ranges from -1 to 1: A value of +1 indicates a perfect positive linear relationship, while a value of -1 indicates a perfect negative linear relationship. A value of 0 suggests no linear relationship between the variables, meaning changes in one do not influence the other.

Multiple Regression

After getting a general sense of the data, we conduct multiple regression analysis to examine the relationship between the dependent variable, Median House Value (MEDHVAL), and the predictors, education attainment (PCTBACHMOR), number of Households Living in Poverty (NBELPOV100), percentage of Vacant Houses (PCTVACANT), and percentage of Single House Units (PCTSINGLES). Regression analysis is a statistical method to examine the relationship between a dependent variable and one or more predictors. With this type of analysis, researchers can identify the strength and direction of the relationship between variables, make predictions, and assess the significance of predictors. The model also estimates coefficients for each predictor, which represent the expected change in the dependent variable for a one-unit change in the predictor, holding other predictors constant. For this study, the multiple regression model is formulated as follows: \[ \text{LNMEDHVAL} = \beta_0 + \beta_1 \text{PCTVACANT} + \beta_2 \text{PCTSINGLES} + \beta_3 \text{PCTBACHMOR} + \beta_4 \text{log(NBELPOV100)} + \epsilon \] where LNMEDHVAL is the log-transformed median house value, PCTVACANT is the proportion of vacant housing units , PCTSINGLES is the proportion of the single family housing , PCTBACHMOR is the percentage of the residents holding bachelor’s degree or higher, and log(NBELPOV100) is the log-transformed number of households living below the poverty line.

\(\beta_0\) is the intercept, \(\beta_1\), \(\beta_2\), \(\beta_3\), and \(\beta_4\) are the coefficients for each predictor, and \(\epsilon\) is the error term. The coefficient \(\beta_1\), \(\beta_2\), \(\beta_3\), \(\beta_4\) represent the change in the log-transformed median house value for a one-unit change in the corresponding predictor, holding other predictors constant. The error term \(\epsilon\) accounts for the variability in the dependent variable that is not explained by the predictors.

Regression Assumptions

There are several assumptions associated with regression analysis that need to be met for the results to be valid. These assumptions including linearity, independence of observations, homoscedasticity, normality of residuals, no multicollinearity, and no fewer than 10 observations per predictors.

First, Linearity assumes that the relationship between the dependent variable and the predictors is linear. To verify this assumption, we made scatter plots of the dependent variable against each predictor. If the relationship appears to be linear, the assumptions was met.

Second, Independence of Observations assumes that the observations are independent of each other. There should be no spatial or temporal or other forms of dependence in the data.

Third, Homoscedasticity assumes that the variance of the residuals \(\epsilon\) is constant regardless of the values of each level of the predictors. To check this assumption, we made a scatter plot of the standardized residuals against the predicted values. If the residuals are evenly spread around zero, the assumption was met. Any patterns may indicate the presence of heteroscedasticity.

Fourth, Normality of Residuals assumes that the residuals are normally distributed. We examined the histogram of the standardized residuals to check if they are approximately normally distributed. If the histogram is bell-shaped, the assumption was met.

Fifth, No Multicollinearity assumes that the predictors are not highly correlated with each other. We calculated the correlation matrix of the predictors to check for multicollinearity. If the correlation coefficients are is not greater than 0.8 or less than -0.8, the assumption was met.

Finally, No Fewer than 10 Observations per Predictor assumes that there are at least 10 observations for each predictor in the model. Since there are over 1,700 observations in the dataset, this assumption was met.

Parameter Estimations

After verifing the assumptions of the regression, we start the regression analysis. Several parameters need to estimate here: - \(\beta_0\), which is the intercept - \(\beta_1, \dots, \beta_k\), which are coefficients of each independent variables - \(\sigma^2\), the variance of the error terms, which represents the variability in the dependent variable that is not explained by the predictors.

The least squares method estimates the coefficients by minimizing the sum of squared errors (SSE), which is the sum of the squared differences between the observed values and the predicted values. The formula for SSE is:

\[ \text{SSE} = \sum_{i=1}^{n} (y_i - \hat{y}_i)^2 = \sum_{i=1}^{n} (y_i - \hat{\beta}_0 - \hat{\beta}_1 x_{i1} - \dots - \hat{\beta}_k x_{ik})^2 \] where \(y_i\) is the actual or observed value, \(\hat{y}_i\) is the predicted value, \(\hat{\beta}_0, \dots, \hat{\beta}_k\) are the estimated coefficients, and \(x_{i1}, \dots, x_{ik}\) are the predictor values for the \(i\)-th observation.

With the Error Sum of Squares (SSE) calculated, we can estimate the variance of the error terms \(\sigma^2\) using the formula:

\[ \sigma^2 = \frac{\text{SSE}}{n - (k+1)} \] where \(n\) is the number of observations and \(k\) is the number of predictors in the model.

Model Evaluation

We evaluated the model’s fitness using the coefficient of determination \(R^2\) and the adjusted \(R^2\). The coefficient of determination \(R^2\) measures the proportion of variance in the dependent variable that is explained by the predictors. The adjusted \(R^2\) adjusts the \(R^2\) value based on the number of predictors, which help to provide a more accurate measure of model fit for multiple regression, as the increase the number of predictors can artificially inflate the \(R^2\) value.

To obtain \(R^2\), \(SST\) or the total sum of squares, needed to be calculated first. The \(SST\) measures the total variance in the dependent variable, given by: \[ SST = \sum_{i=1}^{n} (y_i - \bar{y})^2 \] Where \(y_i\) is the observed value, and \(\bar{y}\) is the mean of the observed value. Then, the \(R^2\) can be obtained by: \[ R^2 = 1 - \frac{SSE}{SST} \] After that, \(R^2\) is adjusted as follows based on the number of observations \(n\) and the number of predictors \(k\): \[ R^2_{\text{adj}} = 1 - \frac{(1 - R^2)(n - 1)}{n - k - 1} \]

Hypothesis Testing

In this analysis. several hypothesis tests are conducted to determine the significance of the model and its predictors. The overall significance of the model is assessed using the F-ratio. It compares the variance explained by the model to the variance not explained by the model.A higher F-ratio indicates that the model explains a significant amount of variance in the dependent variable compared to the residual variance.

The null hypothesis and alternative hypothesis for the F-ratio are stated as follows:

  • The null hypothesis \(H_0\) states that all coefficients are equal to zero, meaning that the predictors do not explain the variance in the dependent variable (median house value). Stated as:

    \[ H_0: \beta_1 = \beta_2 = \beta_3 = \beta_4 = 0 \]

  • The alternative hypothesis \(H_a\) states that at least one coefficient is not equal to zero. In our case, this means that at least one predictor explains the variance in the dependent variable (median house value). Stated as: \[ H_a: \text{At least one } \beta_i \neq 0 \]

We also conduct a t-test to determine the significance of each individual predictor in the model:

  • The null hypothesis \(H_{0i}\) states that the coefficient for the predictor i is equal to zero, meaning that the predictor does not explain the variance in the dependent variable (median house value). Stated as:

    \[ H_{0i}: \beta_i = 0 \]

  • The alternative hypothesis \(H_{ai}\) states that the coefficient for the predictor i is not equal to zero, meaning that the predictor explains the variance in the dependent variable (median house value). Stated as:

    \[ H_{ai}: \beta_i \neq 0 \]

Additional Analysis

Stepwise Regression

In addition to the multiple regression analysis, we conduct stepwise regression analysis to identify the most significant predictors of median house values in Philadelphia. Stepwise regression is a method that automatically selects the best subset of predictors for the model. It involves adding or removing predictors based on their statistical significance (P-value) and the AIC (Akaike Information Criterion). The stepwise regression analysis will help us identify the most important predictors and improve the overall model fits.

However, there are several limitations to stepwise regression. First, the final stepwise regression model is not guaranteed to be optimal in any specific sense. There may be other models that are as good as, or even better than the one selected by stepwise regression, but the procedure only yeilds a single model. Second, the stepwise regression does take into account researchers’ knowledge about the predictors. Important variables may be exclude from the model if they are not included in the initially. Moreover, This method also runs the risk of Type I and Type II errors—meaning it may include unimportant variables or exclude important ones.

Cross-Validation

To evaluate the performance of the regression model, we conduct K-fold cross-validation. Cross-validation is a technique used to evluate the performance of the predictive models. In K-fold Cross-Validation, the dataset is randomly divided into K equal-sized folds. The model is trained on K-1 folds and tested on the remaining fold. This process is repeated K times, with each fold serving as the test set exactly once. The average performance across all K folds is then calculated. Cross-validation helps to assess the model’s generalization performance and reduce the risk of overfitting.

In our analysis, we used K=5, which is a common choice for cross-validation. The root mean squared error (RMSE) is used to compare the performance of different models. The RMSE measures the difference between the predicted values and the actual values. A lower value of RMSE indicates a better predictive model.

The mean square errors is calculated as follows: \[ \text{MSE} = \frac{1}{n} \sum_{i=1}^{n} (y_i - \hat{y}_i)^2 \] And the root mean square errors (RMSE) is the square root of the mean square errors (MSE): \[ \text{RMSE} = \sqrt{\text{MSE}} \]

Software and Packages

In this analysis, we utilize the R programming language, a professional statistical software widely used for data analysis and visualization.The following libraries and packages have been employed to conduct the analysis:

  • tidyverse: A collection of R packages for data manipulation and visualization.
  • sf: A package for spatial data processing, especially for handling shapefiles.
  • ggplot2: A popular visualization package for creating high-quality map and charts, part of the tidyverse collection.
  • ggcorrplot: A package designated to visualize correlation matrices using ggplot2.
  • patchwork: A package for combining multiple ggplot2 plots into a single plot.
  • MASS: A package provides multiple functions and datasets for statistical analysis, including linear models.
  • caret: A package for creating predictive models and conducting machine learning tasks, used in cross-validation and k-fold analysis.
  • kableExtra: A package for creating tables with advanced formatting options.

Results

Exploratory Results

The table below presents the summary statistics for the key variables, an overview of the central tendency and variability. The dependent variable median house value has a mean of 66,287.73, indicating that the average median house value by census tract in Philadelphia is approximately 66,287.73 dollar. The standard deviation of 60,006.08 dollar suggests that house values exhibit significant variability across census tracts.

For the predictor variables, all have standard deviations close to or greater than the mean, indicating large differences in educational attainment, economic status, housing occupancy, and housing structure composition across Philadelphia’s census block groups.

dependent_var <- "MEDHVAL"

predictors <- c("PCTBACHMOR", "NBELPOV100", "PCTVACANT", "PCTSINGLES")

summary_stats <- data %>%
  dplyr::select(all_of(c(dependent_var, predictors))) %>%
  summarise_all(list(Mean = mean, SD = sd), na.rm = TRUE) %>%
  pivot_longer(cols = everything(), names_to = "Variable", values_to = "Value") %>%
  separate(Variable, into = c("Variable", "Stat"), sep = "_") %>%
  pivot_wider(names_from = Stat, values_from = Value)



summary_stats$Variable <- recode(summary_stats$Variable,
  "MEDHVAL" = "Median House Value",
  "NBELPOV100" = "# Households Living in Poverty",
  "PCTBACHMOR" = "% of Individuals with Bachelor’s Degrees or Higher",
  "PCTVACANT" = "% of Vacant Houses",
  "PCTSINGLES" = "% of Single House Units"
)



summary_stats <- summary_stats %>%
  mutate(
    Mean = round(Mean, 2),
    SD = round(SD, 2)
  )

summary_stats <- summary_stats %>%
  arrange(Variable == "Median House Value")

predictor_rows <- which(summary_stats$Variable != "Median House Value")
dependent_rows <- which(summary_stats$Variable == "Median House Value")

# Determine the start and end rows for each group
start_pred <- min(predictor_rows)
end_pred   <- max(predictor_rows)
start_dep  <- min(dependent_rows)
end_dep    <- max(dependent_rows)

# Create the table using kable and add extra formatting
kable(summary_stats, caption = "Summary Statistics", 
      align = c("l", "l", "l"), booktabs = TRUE, escape = FALSE ) %>%
  add_header_above(c(" " = 1, "Statistics" = 2)) %>%
  kable_styling(full_width = FALSE) %>%
  group_rows("Predictors", start_pred, end_pred) %>%
  group_rows("Dependent Variable", start_dep, end_dep)%>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = TRUE)
Summary Statistics
Statistics
Variable Mean SD
Predictors
% of Individuals with Bachelor’s Degrees or Higher 16.08 17.77
# Households Living in Poverty 189.77 164.32
% of Vacant Houses 11.29 9.63
% of Single House Units 9.23 13.25
Dependent Variable
Median House Value 66287.73 60006.08

Histogram Distribution

One of the assumptions of OLS regression is that variables follow a normal distribution. To assess the distribution of key variables, their histograms are presented below. As seen in the plots, all key variables exhibit left-skewness, meaning their distributions are right-skewed (positively skewed), with a concentration of smaller values and a long right tail.

longer_version<- data %>%
  pivot_longer(cols = c("MEDHVAL", "PCTBACHMOR", "NBELPOV100", "PCTVACANT", "PCTSINGLES"),
               names_to = "Variable",
               values_to = "Value")

ggplot(longer_version,aes(x = Value)) +
  geom_histogram(aes(y = ..count..), fill = "black", alpha = 0.7) +  
  facet_wrap(~Variable, scales = "free", ncol = 3, labeller = as_labeller(c(
    "MEDHVAL" = "Median House Value",
    "PCTBACHMOR" = "% with Bachelor’s Degrees or Higher",
    "NBELPOV100" = "# Households Living in Poverty",
    "PCTVACANT" = "% of Vacant Houses",
    "PCTSINGLES" = "% of Single House Units"
  ))) +  
  labs(x = "Value", y = "Count", title = "Histograms of Dependent and Predictor Variables") +
  theme_light() +   
  theme(plot.subtitle = element_text(size = 9,face = "italic"),
        plot.title = element_text(size = 12, face = "bold"), 
        axis.text.x=element_text(size=6),
        axis.text.y=element_text(size=6), 
        axis.title=element_text(size=8))

To meet the normality assumption of OLS, log transformation is applied where necessary to improve distributional symmetry. This transformation helps normalize the distributions, making them more suitable for regression analysis. The histograms of the log-transformed variables indicate a more normal-like distribution. However, some slight skewness remains: the dependent variable (Log Median House Value) and the predictor (Log % Single House Value) are slightly left-skewed, while the predictors Log % Households in Poverty and Log % Vacant Houses are slightly right-skewed.

data <- data %>%
  mutate(
    LNMEDHVAL = log(MEDHVAL),
    LNPCTBACHMOR = log(1+PCTBACHMOR),
    LNNBELPOV100 = log(1+NBELPOV100),
    LNPCTVACANT = log(1+PCTVACANT),
    LNPCTSINGLES = log(1+PCTSINGLES)
  )
longer_version2 <- data %>%
  pivot_longer(cols = c(LNMEDHVAL, LNPCTBACHMOR ,LNNBELPOV100,LNPCTVACANT, LNPCTSINGLES),
               names_to = "Variable",
               values_to = "Value")

ggplot(longer_version2,aes(x = Value)) +
  geom_histogram(aes(y = ..count..), fill = "red", alpha = 0.7) +  
  facet_wrap(~Variable, scales = "free", ncol = 3, labeller = as_labeller(c(
    "LNMEDHVAL" = "Log Median House Value",
    "LNPCTBACHMOR" = "Log % with Bachelor’s Degree",
    "LNNBELPOV100" = "Log # Households in Poverty",
    "LNPCTVACANT" = "Log % Vacant Houses",
    "LNPCTSINGLES" = "Log % Single House Units"
  ))) +  
  labs(x = "Value", y = "Count", title = "Histograms of Dependent and log transformed Predictor Variables") +
  theme_light() +   
  theme(plot.subtitle = element_text(size = 9,face = "italic"),
        plot.title = element_text(size = 12, face = "bold"), 
        axis.text.x=element_text(size=6),
        axis.text.y=element_text(size=6), 
        axis.title=element_text(size=8))

Other regression assumptions will be assessed separately in the Regression Assumption Checks section later.

Choropleth Maps

Linearity assumes that the relationship between the dependent variable and the predictors is linear. To examine this relationship, we analyze the spatial distribution of key variables. Certain predictor maps exhibit patterns similar to the dependent variable, suggesting a strong potential relationship.

Below is the choropleth map of the dependent variable, Log Transformed Median House Value. It reveals that central city areas and Germantown/Chestnut Hill have higher median house values, while North Philadelphia has lower values.

ggplot(shape) +
  geom_sf(aes(fill = LNMEDHVAL), color = "transparent") +
  scale_fill_gradientn(colors = c("#fff0f3", "#a4133c"), 
                       name = "LNMEDHVAL", 
                       na.value = "transparent") + 
  theme(legend.text = element_text(size = 9),
        legend.title = element_text(size = 10),
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank(),
        axis.text.y = element_blank(),
        axis.ticks.y = element_blank(),
        plot.subtitle = element_text(size = 9, face = "italic"),
        plot.title = element_text(size = 12, face = "bold"),
        panel.background = element_blank(),
        panel.border = element_rect(colour = "grey", fill = NA, size = 0.8)) +
  labs(title = "Log Transformed Median House Value")

To understand the spatial relationship between the dependent variable and predictors, we present four key predictor maps below as well.

shpe_longer<- shape %>%
  pivot_longer(cols = c("PCTVACANT", "PCTSINGLES", "PCTBACHMOR", "LNNBELPOV"),
               names_to = "Variable",
               values_to = "Value")
custom_titles <- c(
  PCTVACANT   = "Percent of Vacant Houses",
  PCTSINGLES  = "Percent of Single House Units",
  PCTBACHMOR  = "Percent of Bachelor's Degree or Higher",
  LNNBELPOV   = "Logged Transformed Poverty Rate"
)



plot_list <- lapply(unique(shpe_longer$Variable), function(var_name) {
  data_subset <- subset(shpe_longer, Variable == var_name)
  
  ggplot(data_subset) +
    geom_sf(aes(fill = Value), color = "transparent") +
    scale_fill_gradientn(
      colors = c("#fff0f3", "#a4133c"),
      name = var_name,
      na.value = "transparent"
    ) +
    labs(title = custom_titles[[var_name]]) +
    theme(
      legend.text = element_text(size = 8),
      legend.title = element_text(size = 10),
      legend.key.size = unit(0.3, "cm"),
      axis.text.x = element_blank(),
      axis.ticks.x = element_blank(),
      axis.text.y = element_blank(),
      axis.ticks.y = element_blank(),
      plot.subtitle = element_text(size = 9, face = "italic"),
      plot.title = element_text(size = 15, face = "bold"),
      panel.background = element_blank(),
      panel.border = element_rect(colour = "grey", fill = NA, size = 0.8)
    )
})

# Combine the plots into a grid (2 columns by 2 rows)
combined_plot <- (plot_list[[1]] + plot_list[[2]]) /
                 (plot_list[[3]] + plot_list[[4]])

combined_plot

These maps also help identify whether predictors are closely related to each other, which could cause multicollinearity problems. The Percent of Bachelor’s Degree or Higher map looks very similar to the Log Transformed Median House Value map, suggesting that areas with more college graduates tend to have higher house values. Also, the Percent of Vacant Houses and Percent of Single House Units maps share a similar pattern—North Philadelphia and University City have a high percentage of vacant houses and a low percentage of single-house units, while Germantown/Chestnut Hill and Far Northeast Philadelphia show the opposite trend. This suggests that these two predictors may be strongly related, which could lead to multicollinearity issues in the regression analysis.

Examining Multicollinearity & Correlation Matrix

To further examine multicollinearity, we create a correlation matrix between predictors. All correlation values are below 0.7, indicating that no severe multicollinearity occurs in our model.

Among them, % of Single House Units and Logged Households Living in Poverty have a correlation of -0.32, suggesting some relationship but not strong enough to cause severe multicollinearity. Looking back at the choropleth maps of these two predictors, their spatial patterns are not similar. % of Single House Units and % of Individuals with a Bachelor’s Degree or Higher have a correlation of -0.3, again indicating some relationship without severe multicollinearity. The choropleth maps of these two predictors also do not exhibit similar spatial patterns. Additionally, while the choropleth maps of Percent of Vacant Houses and Percent of Single House Units share a similar pattern, as mentioned before, their correlation value is only 0.2, suggesting a weak relationship without multicollinearity.

There is no severe multicollinearity among the predictors, supporting the assumptions of OLS regression. However, if the correlation matrix had shown high correlations (\(|r| \)), we could further confirm the severity of multicollinearity using the Variance Inflation Factor (VIF) (VIF < 5 indicates low multicollinearity and is generally acceptable, while VIF \(\geq\) 5 suggests moderate to high multicollinearity that may require attention. If VIF \(\geq\) 10, severe multicollinearity is present, necessitating corrective measures).

custom_labels <- c(
  "% of Individuals with Bachelor’s Degrees or Higher" = "PCTBACHMOR",
  "% of Vacant Houses" = "PCTVACANT",
  "% of Single House Units" = "PCTSINGLES",
  "# Households Living in Poverty" = "LNNBELPOV100"
)

predictor_vars <- data[, c("PCTVACANT", "PCTSINGLES", "PCTBACHMOR", "LNNBELPOV100")]

cor_matrix <- cor(predictor_vars, use = "complete.obs", method = "pearson")

print(cor_matrix)
##               PCTVACANT PCTSINGLES PCTBACHMOR LNNBELPOV100
## PCTVACANT     1.0000000 -0.1513734 -0.2983580    0.2495470
## PCTSINGLES   -0.1513734  1.0000000  0.1975461   -0.2905159
## PCTBACHMOR   -0.2983580  0.1975461  1.0000000   -0.3197668
## LNNBELPOV100  0.2495470 -0.2905159 -0.3197668    1.0000000
rownames(cor_matrix) <- names(custom_labels)
colnames(cor_matrix) <- names(custom_labels)


ggcorrplot(cor_matrix, 
           method = "square",   
           type = "lower",      
           lab = TRUE,       
           lab_size = 3,      
           colors = c("#d73027", "white", "#1a9850"))+
    labs(title = "Correlation Matrix for all Predictor Variables") +
    theme(plot.subtitle = element_text(size = 9, face = "italic"),
        plot.title = element_text(size = 12, face = "bold"), 
        axis.text.x = element_text(size = 7),
        axis.text.y = element_text(size = 7), 
        axis.title = element_text(size = 8))

Regression Results

Parameter Estimations

Four independent variables were included in the multiple regression model to predict the log-transformed median house value (LNMEDHVAL) in Philadelphia at census block group level, including the proportion of vacant housing units (PCTVACANT), the proportion of single-family housing units (PCTSINGLES), the proportion of residents with a bachelor’s degree or higher (PCTBACHMOR), and the number of households living below the poverty line (LNNBELPOV100). The regression results are presented below:

fit <- lm(LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR + LNNBELPOV100, data=data)
summary(fit)
## 
## Call:
## lm(formula = LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR + 
##     LNNBELPOV100, data = data)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -2.25825 -0.20391  0.03822  0.21744  2.24347 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  11.1137661  0.0465330 238.836  < 2e-16 ***
## PCTVACANT    -0.0191569  0.0009779 -19.590  < 2e-16 ***
## PCTSINGLES    0.0029769  0.0007032   4.234 2.42e-05 ***
## PCTBACHMOR    0.0209098  0.0005432  38.494  < 2e-16 ***
## LNNBELPOV100 -0.0789054  0.0084569  -9.330  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.3665 on 1715 degrees of freedom
## Multiple R-squared:  0.6623, Adjusted R-squared:  0.6615 
## F-statistic: 840.9 on 4 and 1715 DF,  p-value: < 2.2e-16

The regression output tells us that the median housing values are highly significant correlated with the proportion of vacant housing units(PCTVANT), the proportion of single-family housing units(PCTSINGLES), the proportion of residents with a bachelor’s degree or higher (PCTBACHMOR), and the log-transformed number of households living below the poverty line (LNNBELPOV), with \(p-value<0.0001\) for all four predictors.

As the proportions of vacant housing units (PCTVANT) goes up by 1 unit (1%), the median house value goes down by approximately 1.915%, with holding all other three predictors constant. In addition, the respective \(p-value\) for \(\beta_1\) is less than 0.0001, indicating that if there is no relationship between PCTVANT and the dependent variable (i.e., if the null hypothesis that \(\beta_1 = 0\) is true), then the probability of getting a \(\beta_1\) coefficient estimate of -0.0191569 is less than 0.0001. We can safely reject the null hypothesis \(H_0: \beta_1 = 0\) for \(H_a: \beta_1 \neq 0\).

\[(e^{\beta} - 1) \times 100\% = (e^{-0.0191569} - 1) \times 100\% \approx -1.915\% \]

Similarly, as the proportion of single-family housing units (PCTSINGLES) goes up by 1 unit (1%), the median house value goes up by approximately 0.298%, with holding all other three predictors constant. The \(p-value\) for \(\beta_2\) is less than 0.0001, indicating that if there is no relationship between PCTSINGLES and the dependent variable (i.e., if the null hypothesis that \(\beta_2 = 0\) is true), then the probability of getting a \(\beta_2\) coefficient estimate of 0.0029769 is less than 0.0001. We can also safely reject the null hypothesis \(H_0: \beta_2 = 0\) for \(H_a: \beta_2 \neq 0\).

\[(e^{\beta} - 1) \times 100\% = (e^{-0.0029769} - 1) \times 100\% \approx 0.298\% \]

Furthermore, as the proportion of residents with a bachelor’s degree or higher (PCTBACHMOR) goes up by 1 unit (1%), the median house value goes up by approximately 2.09%, with holding all other three predictors constant. Similar to \(\beta_2\), the \(p-value\) for \(\beta_3\) is less than 0.0001, indicating that if there is no relationship between PCTBACHMOR and the dependent variable (i.e., if the null hypothesis that \(\beta_3 = 0\) is true, then the probability of getting a \(\beta_3\) coefficient estimate of 0.0209098 is less than 0.0001. We can also safely reject the null hypothesis \(H_0: \beta_3 = 0\) for \(H_a: \beta_3 \neq 0\).

\[(e^{\beta} - 1) \times 100\% = (e^{0.0209098} - 1) \times 100\% \approx 2.09\% \]

Lastly, as 1 percent increase in the number of households living below the poverty line, the median house value goes down by approximately 0.078% , with holding all other three predictors constant. The \(p-value\) for \(\beta_4\) is also less than 0.0001 indicating that if there is no relationship between number of households below poverty line and the dependent variable (i.e., if the null hypothesis that \(\beta_4 = 0\) is true), then the probability of getting a \(\beta_4\) coefficient estimate of -0.0789054 is less than 0.0001. As stated before, we can also safely reject the null hypothesis \(H_0: \beta_4 = 0\) for \(H_a: \beta_4 \neq 0\).

\[(1.01^{\beta} - 1) \times 100\% = (1.01^{-0.0789054} - 1) \times 100\% \approx -0.078\%\]

Model Fit

fit <- lm(LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR + LNNBELPOV100, data=data)
summary(fit)
## 
## Call:
## lm(formula = LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR + 
##     LNNBELPOV100, data = data)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -2.25825 -0.20391  0.03822  0.21744  2.24347 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  11.1137661  0.0465330 238.836  < 2e-16 ***
## PCTVACANT    -0.0191569  0.0009779 -19.590  < 2e-16 ***
## PCTSINGLES    0.0029769  0.0007032   4.234 2.42e-05 ***
## PCTBACHMOR    0.0209098  0.0005432  38.494  < 2e-16 ***
## LNNBELPOV100 -0.0789054  0.0084569  -9.330  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.3665 on 1715 degrees of freedom
## Multiple R-squared:  0.6623, Adjusted R-squared:  0.6615 
## F-statistic: 840.9 on 4 and 1715 DF,  p-value: < 2.2e-16

First, the residuals from the model show a reasonable distribution of errors, with a median residual of 0.03822, a minimum value of -2.26, a first quartile of -0.20, and a third quartile of 0.22, and a maximum value of 2.24. This distribution shows that the model captures the variability in the dependent variable well (logged transformed median home value), although some of the residuals are larger than 2.5 standard deviations from the mean, which are the outliers.

Moreover, the model has a multiple \(R^2\) value of 0.6623 and an adjusted \(R^2\) value of 0.6615, indicating that approximately 66% of the variance in LNMEDHVAL is explained by the predictors. The \(F-statistic\) of 840.0 with a \(p-value\) less than 0.0001, indicating that the model is statistically significant.

anova_table <- anova(fit)
anova_table
## Analysis of Variance Table
## 
## Response: LNMEDHVAL
##                Df  Sum Sq Mean Sq  F value    Pr(>F)    
## PCTVACANT       1 180.392 180.392 1343.087 < 2.2e-16 ***
## PCTSINGLES      1  24.543  24.543  182.734 < 2.2e-16 ***
## PCTBACHMOR      1 235.118 235.118 1750.551 < 2.2e-16 ***
## LNNBELPOV100    1  11.692  11.692   87.054 < 2.2e-16 ***
## Residuals    1715 230.344   0.134                       
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

The Analysis of Variance (ANOVA) table shows additional insight into the significance of each predictor in explaining the variation in the dependent variable (LNVMEDHVAL). For proportion of vacant housing units (PCTVACANT), the sum of squares is 180.392, indicating that those amount of variation in LNVMEDHVAL that can be attributed to changes in PCTVACANT. A higher sum of squares indicates a mhigher relationship between the predictor and the dependent variable. The sum of squares for the percentage of residents with a bachelor’s degree or higher (PCTBACHMOR) explains the highest portion of the variance in LNVMEDHVAL. In contrast, the sum of squares for the log-transformed number of households living below the poverty line (LNNBELPOV100) explains the least amount of variance in LNVMEDHVAL, with only 11.69.

The total sum of squares, which represents the total variance in the dependent variable (LNVMEDHVAL), is 230.34, with a mean square error of 0.134. Overall, the ANOVA table provides a comprehensive overview of the significance of each predictor in the model and the proportion of variance explained by each predictor. It confirms that all four predictors contribute significantly to explaining the variance in the dependent variable. These findings provide strong evidence of the robustness of the model and the relevance of neighbourhood characteristics in predicting housing values.

Regression Assumptions Check

In this section, we conducted variety of analysis to check if the assumption of the linear regression were met. In the earlier section, we already checked the variable distribution and multicollinearity. Here, we will check following assumption:

  • Linearity
  • Normality of Residuals
  • Homoscedasticity

Linearity

To further examine the linear relationship between the dependent variable and the predictors, we create four scatter plots, where the x-axis represents each predictor and the y-axis represents the dependent variable, Log Transformed Median House Value.

longer<-data %>%
  pivot_longer(cols = c("PCTBACHMOR", "LNNBELPOV100", "PCTVACANT", "PCTSINGLES"),
               names_to = "Variable",
               values_to = "Value")

ggplot(longer,aes(x = Value, y = LNMEDHVAL)) +
  geom_point(color = "black", size= 0.4) +
  geom_smooth(method = "lm", color = "red", se = FALSE) + 
  facet_wrap(~ Variable, scales = "free", labeller = as_labeller(c(
    "PCTBACHMOR" = "% with Bachelor’s Degrees or Higher",
    "LNNBELPOV100" = "Logged Households Living in Poverty",
    "PCTVACANT" = "% of Vacant Houses",
    "PCTSINGLES" = "% of Single House Units"
  )))  +
  theme_light() +   
  theme(plot.subtitle = element_text(size = 9,face = "italic"),
        plot.title = element_text(size = 12, face = "bold"), 
        axis.text.x=element_text(size=6),
        axis.text.y=element_text(size=6), 
        axis.title=element_text(size=8)) +
  labs(title = "Scatter Plots of Dependent Variable vs. Predictors", 
       x = "Predictor Value", 
       y = "Log of Median House Value")

From the plots, we observe the following trends:

  • Logged Households Living in Poverty shows a negative linear relationship with the dependent variable. As the percentage of households living in poverty increases, the Log Transformed Median House Value decreases. This is reflected in its correlation coefficient \(< 0\). However, the association is not strictly linear. In the graph, the points are more scattered widely, particular at lower level of poverty, where housing values vary significantly. This indicate while poverty levels have a negative impact on housing values, the effect is not uniform across all block groups. There is a substantial variation in housing values even at similar poverty levels, which suggests that other factors may also be influencing housing values.

  • % with Bachelor’s Degrees or Higher exhibits a positive linear relationship with the dependent variable. When the percentage of individuals with a bachelor’s degree or higher increases, the Log Transformed Median House Value also rises, with a correlation coefficient \(> 0\). The points on the graph form a tight band along the trend line, indicating that higher education levels within a neighborhood is highly correlated with higher housing values. The consistent upward trend suggest that educational attainment is a key driver of housing prices, and a clear linear trend implies that this variable is suitable for this linear regression analysis.

  • % of Single House Units has a weaker but still positive relationship with the dependent variable. While the trend is not obvious, areas with a higher percentage of single-house units tend to have higher Log Transformed Median House Values, especially when the percentage is sufficiently large. The correlation coefficient is \(> 0\). The scatter points shows significant variability in housing values at various levels of single-house units, with some block groups having high housing values despite a low percentage of single-house units. This variability suggests that while there is a positive relationship between single-house units and housing values, other factors may also be influencing housing values at the same time.

  • % of Vacant Houses has a general negative linear relationship with the dependent variable. As the percentage of vacant houses increases, the Log Transformed Median House Value decreases, with a correlation coefficient \(< 0\). However, in the graph, it reveals a more complex relationship with significant variation in housing values across different vacancy rates. There are clusters of block groups with high housing values and low vacancy rates, indicating that the relationship is not strictly linear.In the middle and lower ranges of vacancy rates, the decline in housing values becomes less pronounced. This suggests that while vacant housing is associated with lower property values, the impact diminishes or becomes less predictable as the vacancy rate changes.

In summary, the scatterplot shows that while the PCTBACHMOR and LNMEDHVAL have a clear linear relationship, the other predictors have more complex non-linear relationships with the dependent variable. This suggests that the linear regression model may not fully capture the complexity of the relationships between the predictors and median house values.

Normality of Residuals

Next, we examine the normality of residuals of the regression model. The histogram of standardized residuals provides a detail view of the of the distribution of the residuals from the OLS model, showing below:

ggplot(data, aes(x = Standardized_Residuals)) +
  geom_histogram(bins = 30, fill = "black") +
  labs(title = "Histogram of Standardized Residuals", 
       x = "Standardized Residuals", 
       y = "Frequency") +
  theme_minimal() +   
  theme(plot.subtitle = element_text(size = 9,face = "italic"),
        plot.title = element_text(size = 12, face = "bold"), 
        axis.text.x=element_text(size=6),
        axis.text.y=element_text(size=6), 
        axis.title=element_text(size=8))

ggplot(data, aes(x = Fitted, y = Standardized_Residuals)) +
  geom_point(color = "black", size= 0.4) +    
  geom_hline(yintercept = 0, linetype = "dashed", color = "red") +  
  labs(
    title = "Scatter Plot of Standardized Residuals vs Fitted Values",
    x = "Predicted Values",
    y = "Standardized Residuals"
  ) +
  theme_minimal() +   
  theme(plot.subtitle = element_text(size = 9,face = "italic"),
        plot.title = element_text(size = 12, face = "bold"), 
        axis.text.x=element_text(size=6),
        axis.text.y=element_text(size=6), 
        axis.title=element_text(size=8))

join<- data %>%
  dplyr::select(POLY_ID, Standardized_Residuals)

shape <- shape %>%
  left_join(join, by = c("POLY_ID" = "POLY_ID"))

ggplot(shape)+
  geom_sf(aes(fill = Standardized_Residuals), color = "transparent") +
  scale_fill_gradientn(colors = c("#fff0f3", "#a4133c"), 
                       name = "Std Residuals", 
                       na.value = "transparent") +  # Choose a color palette, invert direction if needed
  labs(title = "Choropleth Map of Standardized Residuals") +
  theme(legend.text = element_text(size = 9),
        legend.title = element_text(size = 10),
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank(),
        axis.text.y = element_blank(),
        axis.ticks.y = element_blank(),
        plot.subtitle = element_text(size = 9, face = "italic"),
        plot.title = element_text(size = 12, face = "bold"),
        panel.background = element_blank(),
        panel.border = element_rect(colour = "grey", fill = NA, size = 0.8))

Additional Analysis

stepwise_model <-  stepAIC(fit, direction = "both")
## Start:  AIC=-3448.07
## LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR + LNNBELPOV100
## 
##                Df Sum of Sq    RSS     AIC
## <none>                      230.34 -3448.1
## - PCTSINGLES    1     2.407 232.75 -3432.2
## - LNNBELPOV100  1    11.692 242.04 -3364.9
## - PCTVACANT     1    51.546 281.89 -3102.7
## - PCTBACHMOR    1   199.020 429.36 -2379.0
stepwise_model$anova
## Stepwise Model Path 
## Analysis of Deviance Table
## 
## Initial Model:
## LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR + LNNBELPOV100
## 
## Final Model:
## LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR + LNNBELPOV100
## 
## 
##   Step Df Deviance Resid. Df Resid. Dev       AIC
## 1                       1715   230.3435 -3448.073
lm <-  trainControl(method = "cv", number = 5)

cvlm_model <- train(LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR + LNNBELPOV100, data=data, method = "lm", trControl = lm)

print(cvlm_model)
## Linear Regression 
## 
## 1720 samples
##    4 predictor
## 
## No pre-processing
## Resampling: Cross-Validated (5 fold) 
## Summary of sample sizes: 1376, 1376, 1376, 1376, 1376 
## Resampling results:
## 
##   RMSE       Rsquared   MAE      
##   0.3675194  0.6638375  0.2726991
## 
## Tuning parameter 'intercept' was held constant at a value of TRUE
cvlm_model_reduced = train(LNMEDHVAL ~ PCTVACANT + MEDHHINC, data = data, method = "lm", trControl = lm)

print(cvlm_model_reduced)
## Linear Regression 
## 
## 1720 samples
##    2 predictor
## 
## No pre-processing
## Resampling: Cross-Validated (5 fold) 
## Summary of sample sizes: 1376, 1376, 1376, 1376, 1376 
## Resampling results:
## 
##   RMSE       Rsquared   MAE      
##   0.4431696  0.5091175  0.3181327
## 
## Tuning parameter 'intercept' was held constant at a value of TRUE

Discussion

Our regression analysis of Philadelphia’s census block group data clearly shows how neighborhood characteristics affect housing values. Our model explains about 66% of the variation in the log-transformed median house value (LNMEDHVAL). This indicates that factors such as the percentage of vacant houses (PCTVACANT), the percentage of single-family homes (PCTSINGLES), the percentage of residents with at least a bachelor’s degree (PCTBACHMOR), and the log-transformed number of households living below the poverty line (LNNBELPOV100) are all important in shaping housing market outcomes.

Interpreting the Results:

Need to rewrite We cannot include log-transformed value directly into the report, see the above interpret section for the interpretation of the results.

Checking the Model Assumptions:

b) Talk about the quality of the model – that is, state if this is a good model overall (e.g., R2, F-ratio test), and what other predictors that we didn’t include in our model might be associated with our dependent variable. i. Looking at the stepwise regression results, did the final model include all 4 predictors or were some dropped? What does that tell you about the quality of the model? ii. Looking at the cross-validation results, was the RMSE better for the 4 predictor model or the 2 predictor model?

To validate our model, we performed stepwise regression using the Akaike Information Criterion (AIC) and conducted 5-fold cross-validation. The stepwise regression confirmed that the selected predictors contribute to a strong model fit, while the cross-validation results showed that the full model which includes all the four predictors performs better than a reduced model that only includes the percentage of vacant houses (PCTVACANT) and median household income. These results strengthen our confidence in the predictive power and robustness of the model.

Policy Implications: A Focus on Inclusive Growth and Stability: (one paragraph only)

The findings have important implications for urban policy, particularly in ensuring that strategies to improve housing markets do not lead to displacement or increased housing burdens for vulnerable communities. The strong negative impact of vacancy rates (PCTVACANT) on housing values suggests that reducing long-term vacancies could play a role in neighborhood stabilization. However, rather than policies that solely focus on increasing property values, interventions should prioritize equitable investment like rehabilitating vacant properties for affordable housing, expanding community land trusts, and offering support for longtime residents at risk of displacement.

Similarly, the strong relationship between educational attainment (PCTBACHMOR) and housing values highlights the importance of expanding access to high-quality education and workforce development. However, increasing education levels alone does not ensure equitable housing outcomes if housing costs rise beyond affordability for existing residents. Thus, policies should be designed to balance educational investment with affordability measures, such as rental assistance programs and first-time homebuyer support for lower-income households.

The negative association between poverty levels (LNNBELPOV100) and housing values highlights the need for housing policies that actively combat economic inequality and support affordable, stable communities. Solutions such as mixed-income housing developments, income-based tax credits, and expanded tenant protections can help ensure that economic mobility does not come at the cost of displacement. The goal should be to create stable, mixed-income communities where economic growth benefits both current residents and new arrivals.

Limitations and Future Research:

Although our model provides a strong understanding of housing market dynamics, there are several limitations that future research should address. First, while our model explains a significant portion of the variation in housing values, about one-third remains unexplained. This suggests that other factors like access to transportation, historical redlining patterns, or the presence of public amenities may play important roles and should be explored in future studies.

The potential presence of spatial autocorrelation suggests that neighboring block groups may not be entirely independent, which could bias some estimates. Incorporating spatial econometric techniques, such as spatial lag models or geographically weighted regression, could improve the accuracy of future analyses.

Possibility of Ridge or LASSO Regression

Ridge and LASSO regression are used when there are highly correlated predictors or when only a subset of features is expected to be truly important. In such cases, some predictor coefficients may become excessively large, leading to overfitting in a linear model. These methods manage overfitting by adding a penalty term to the loss function, which constrains the coefficients. However, in our model, the highest correlation between predictors is 0.32, indicating no significant multicollinearity. Additionally, no predictor exhibits excessively large coefficients. Therefore, applying Ridge or LASSO regression in this case would be unnecessary.

LS0tCnRpdGxlOiAnVXNpbmcgT0xTIFJlZ3Jlc3Npb24gdG8gUHJlZGljdCBNZWRpYW4gSG91c2UgVmFsdWVzIGluIFBoaWxhZGVscGhpYScKYXV0aG9yOiAiWmhhbmNoYW8gWWFuZywgSGFveXUgWmh1LCBLYXZhbmEgUmFqdSIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZTogZmxhdGx5CiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKICAgIG1hdGhqYXg6IGRlZmF1bHQKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQoKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoc2YpCmxpYnJhcnkodGlkeWNlbnN1cykKbGlicmFyeShrbml0cikgCmxpYnJhcnkoZ3QpIApsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoa2FibGVFeHRyYSkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoZ2djb3JycGxvdCkKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkoTUFTUykKbGlicmFyeShjYXJldCkKYGBgCgpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgaW5jbHVkZT0gRkFMU0V9CiMgTG9hZCB0aGUgZGF0YQpkYXRhIDwtIHJlYWQuY3N2KCJkYXRhL1JlZ3Jlc3Npb25EYXRhLmNzdiIpCnNoYXBlIDwtIHN0X3JlYWQoImRhdGEvUmVncmVzc2lvbkRhdGEuc2hwIikKYGBgCgojIEludHJvZHVjdGlvbgpJbiByZWNlbnQgZGVjYWRlcywgUGhpbGFkZWxwaGlhIGhhcyBleHBlcmllbmNlZCBzdWJzdGFudGlhbCBjaGFuZ2VzIGluIHBvcHVsYXRpb24gZHluYW1pY3MsIGVjb25vbWljIGZsdWN0dWF0aW9ucywgYW5kIHJlZGV2ZWxvcG1lbnQgcHJlc3N1cmVzLiBBbW9uZyB0aGVzZSBjaGFuZ2VzLCBob3VzaW5nIHZhbHVlcyBoYXZlIGJlY29tZSBhIGtleSBpbmRpY2F0b3Igb2YgdGhlIHNvY2lvLWVjb25vbWljIGNvbmRpdGlvbnMgd2l0aGluIHRoZSBjaXR54oCZcyBuZWlnaGJvcmhvb2RzLiBSaXNpbmcgaG91c2luZyB2YWx1ZXMgdHlwaWNhbGx5IHJlZmxlY3QgYSBoaWdoZXIgcHJlc2VuY2Ugb2Ygd2VhbHRoaWVyIHJlc2lkZW50cyBvciBhIG5laWdoYm9yaG9vZCB1bmRlcmdvaW5nIGdlbnRyaWZpY2F0aW9uLCB3aGlsZSBkZWNsaW5pbmcgaG91c2luZyB2YWx1ZXMgb2Z0ZW4gc2lnbmFsIGluY3JlYXNlZCBlY29ub21pYyBwcmVzc3VyZSBvciBkZWNsaW5lLiBUaGVyZWZvcmUsIGFjY3VyYXRlbHkgZm9yZWNhc3RpbmcgdGhlIG1lZGlhbiBob3VzaW5nIHZhbHVlcyBhY3Jvc3MgUGhpbGFkZWxwaGlhIGlzIGNydWNpYWwgZm9yIHVyYmFuIHBsYW5uZXJzIGFuZCBwb2xpY3ltYWtlcnMsIGhlbHBpbmcgdGhlbSB0byBwcm9hY3RpdmVseSBhZGRyZXNzIHBvdGVudGlhbCByaXNrcyBzdWNoIGFzIGRpc3BsYWNlbWVudCBhbmQgZGlzaW52ZXN0bWVudC4gU3VwcG9ydGluZyBQaGlsYWRlbHBoaWHigJlzIGxvbmctdGVybSB2aXNpb24gb2YgZm9zdGVyaW5nIHZpYnJhbnQsIGRpdmVyc2UsIGFuZCByZXNpbGllbnQgY29tbXVuaXRpZXMgaXMgYWxzbyBlc3NlbnRpYWwuCgpUbyBiZXR0ZXIgdW5kZXJzdGFuZCB0aGUgcG90ZW50aWFsIGZhY3RvcnMgaW5mbHVlbmNpbmcgaG91c2luZyB2YWx1ZXMgaW4gUGhpbGFkZWxwaGlhLCB3ZSBpZGVudGlmeSBzZXZlcmFsIGtleSB2YXJpYWJsZXM6IGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQsIHZhY2FuY3kgcmF0ZXMsIHRoZSBwcm9wb3J0aW9uIG9mIHNpbmdsZS1mYW1pbHkgaG9tZXMsIGFuZCBwb3ZlcnR5IGxldmVscy4gVGhlc2UgZmFjdG9ycyBhcmUgY2xvc2VseSByZWxhdGVkIHRvIGhvdXNpbmcgbWFya2V0IHRyZW5kcyBhbmQgcHJvdmlkZSBpbnNpZ2h0cyBpbnRvIHRoZSBuZWlnaGJvcmhvb2TigJlzIHNvY2lvLWVjb25vbWljIHN0YXR1cy4gCgpFZHVjYXRpb25hbCBhdHRhaW5tZW50IGlzIGNsb3NlbHkgbGlua2VkIHRvIHRoZSBzb2Npby1lY29ub21pYyBjaGFyYWN0ZXJpc3RpY3Mgb2YgbmVpZ2hib3Job29kcy4gSW5kaXZpZHVhbHMgd2l0aCBoaWdoZXIgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCB0eXBpY2FsbHkgZWFybiBoaWdoZXIgaW5jb21lcyBhbmQgY29udHJpYnV0ZSBtb3JlIHRvIGxvY2FsIGVjb25vbWllcy4gQSBoaWdoZXIgY29uY2VudHJhdGlvbiBvZiBpbmRpdmlkdWFscyB3aXRoIGFkdmFuY2VkIGVkdWNhdGlvbmFsIGJhY2tncm91bmRzIHRlbmRzIHRvIGluY3JlYXNlIHRoZSBkZW1hbmQgZm9yIHdlbGwtZGVzaWduZWQgaG91c2luZyBpbiBhZmZsdWVudCBuZWlnaGJvcmhvb2RzLiBXaXRoIGEgY29uc2lzdGVudCBzdXBwbHksIGhvdXNpbmcgcHJpY2VzIGFuZCB2YWx1ZXMgYXJlIGxpa2VseSB0byByaXNlLiBTaW1pbGFybHksIGEgaGlnaCBwb3ZlcnR5IHJhdGUgYWxzbyBpbmRpY2F0ZXMgYSBkZWNsaW5pbmcgY29tbXVuaXR5LiBTaW5jZSBtYW55IHJlc2lkZW50cyBjYW5ub3QgYWZmb3JkIGx1eHVyeSBob3VzaW5nLCB0aGUgaG91c2luZyB2YWx1ZXMgaW4gdGhvc2UgbmVpZ2hib3Job29kcyBhcmUgbGlrZWx5IHRvIGJlIExvd2VyLgoKCkhpZ2ggdmFjYW5jeSByYXRlcyBvZnRlbiBjb3JyZWxhdGUgd2l0aCBkZWNsaW5pbmcgbmVpZ2hib3Job29kcyBhbmQgcmVkdWNlZCBtZWRpYW4gaG91c2UgdmFsdWVzLiBSZXNlYXJjaCBzaG93cyB0aGF0IHZhY2FudCBwcm9wZXJ0aWVzIGFmZmVjdCBtdWx0aXBsZSBmYWNldHMgb2YgY29tbXVuaXR5IGxpZmUsIHN1Y2ggYXMgaG91c2luZyBhbmQgbmVpZ2hib3Job29kIHZpdGFsaXR5LCBjcmltZSBwcmV2ZW50aW9uIGVmZm9ydHMsIGFuZCB0aGUgd2VsbC1iZWluZyBvZiBjb21tZXJjaWFsIGRpc3RyaWN0cy4gQXMgYSByZXN1bHQsIGFyZWFzIHdpdGggbnVtZXJvdXMgdmFjYW50IGhvdXNpbmcgdW5pdHMgdHlwaWNhbGx5IHNlZSBkaW1pbmlzaGVkIG1lZGlhbiBob3VzaW5nIHZhbHVlcy4gIAoKClRoZSBwcm9wb3J0aW9uIG9mIHNpbmdsZS1mYW1pbHkgaG9tZXMgaW4gYW4gYXJlYSBpbmZsdWVuY2VzIGhvdXNpbmcgdmFsdWVzLiBUaGVzZSBob21lcyBhcmUgZ2VuZXJhbGx5IHByaXZhdGUgYW5kIGNvbWZvcnRhYmxlLCBtYWtpbmcgdGhlbSBtb3JlIGRlc2lyYWJsZSBpbiBtYW55IFUuUy4gaG91c2luZyBtYXJrZXRzLiAgSG93ZXZlciwgdGhleSBhcmUgcmVsYXRpdmVseSBjb21tb24gaW4gc3VidXJiYW4gbmVpZ2hib3Job29kcyBhbmQgbWF5IHN1ZmZlciBmcm9tIGxvdyBhY2Nlc3NpYmlsaXR5IGFuZCBsaW1pdGVkIGluZnJhc3RydWN0dXJlLCB3aGljaCBjYW4gbmVnYXRpdmVseSBhZmZlY3QgdGhlaXIgcHJvcGVydHkgdmFsdWVzIGFzIHdlbGwuCgpJbiB0aGlzIHN0dWR5LCB3ZSB1dGlsaXplIG9yZGluYXJ5IGxlYXN0IHNxdWFyZXMgKE9MUykgcmVncmVzc2lvbiB0byBhbmFseXplIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGVzZSBzb2Npb2Vjb25vbWljIGZhY3RvcnMgYW5kIG1lZGlhbiBob3VzZSB2YWx1ZXMgaW4gUGhpbGFkZWxwaGlhLiBCeSBleGFtaW5pbmcgdGhlc2UgcmVsYXRpb25zaGlwcywgd2UgYWltIHRvIGlkZW50aWZ5IGNyaXRpY2FsIHByZWRpY3RvcnMgb2YgbWVkaWFuIGhvdXNpbmcgdmFsdWVzIHRocm91Z2hvdXQgUGhpbGFkZWxwaGlhIGFuZCBvZmZlciBpbnNpZ2h0cyBmb3IgZGVjaXNpb24tbWFrZXJzIGFuZCBjb21tdW5pdHkgaW5pdGlhdGl2ZXMuIAoKIyBNZXRob2RzCgojIyBEYXRhIENsZWFuaW5nCgpUbyBwcmVkaWN0IG1lZGlhbiBob3VzZSB2YWx1ZXMgaW4gUGhpbGFkZWxwaGlhLCB3ZSBvYnRhaW5lZCB0aGUgb3JpZ2luYWwgZGF0YXNldCBmcm9tIHRoZSBVbml0ZWQgU3RhdGVzIENlbnN1cyBkYXRhLiBUaGUgZGF0YXNldCByZXByZXNlbnRzIGNlbnN1cyBibG9jayBncm91cHMgZnJvbSB0aGUgeWVhciAyMDAwIGFuZCBpbml0aWFsbHkgY29udGFpbmVkIDEsODE2IG9ic2VydmF0aW9ucy4gVGhlIGtleSB2YXJpYWJsZXMgaW5jbHVkZWQ6CgotICAqKlBPTFlfSUQqKiDigJMgQ2Vuc3VzIEJsb2NrIEdyb3VwIElECi0gICoqTUVESFZBTCoqIOKAkyBNZWRpYW4gdmFsdWUgb2YgYWxsIG93bmVyLW9jY3VwaWVkIGhvdXNpbmcgdW5pdHMKLSAgKipQQ0JBQ0hNT1JFKiog4oCTIFByb3BvcnRpb24gb2YgcmVzaWRlbnRzIGluIHRoZSBibG9jayBncm91cCB3aXRoIGF0IGxlYXN0IGEgYmFjaGVsb3LigJlzIGRlZ3JlZQotICAqKlBDVFZBQ0FOVCoqIOKAkyBQcm9wb3J0aW9uIG9mIGhvdXNpbmcgdW5pdHMgdGhhdCBhcmUgdmFjYW50Ci0gICoqUENUU0lOR0xFUyoqIOKAkyBQZXJjZW50YWdlIG9mIGhvdXNpbmcgdW5pdHMgdGhhdCBhcmUgZGV0YWNoZWQgc2luZ2xlLWZhbWlseSBob3VzZXMKLSAgKipOQkVMUE9WMTAwKiog4oCTIE51bWJlciBvZiBob3VzZWhvbGRzIHdpdGggaW5jb21lcyBiZWxvdyAxMDAlIG9mIHRoZSBwb3ZlcnR5IGxldmVsCi0gICoqTUVESEhJTkMqKiDigJMgTWVkaWFuIGhvdXNlaG9sZCBpbmNvbWUKClRvIHJlZmluZSB0aGUgZGF0YXNldCBmb3IgbW9kZWxpbmcgcHVycG9zZXMsIHdlIGFwcGxpZWQgdGhlIGZvbGxvd2luZyBmaWx0ZXJpbmcgY3JpdGVyaWE6CgooMSkgUmV0YWluZWQgYmxvY2sgZ3JvdXBzIHdpdGggYSBwb3B1bGF0aW9uIGdyZWF0ZXIgdGhhbiA0MAooMikgSW5jbHVkZWQgb25seSBibG9jayBncm91cHMgdGhhdCBjb250YWluZWQgaG91c2luZyB1bml0cwooMykgRXhjbHVkZWQgcmVjb3JkcyB3aGVyZSB0aGUgbWVkaWFuIGhvdXNlIHZhbHVlIHdhcyBiZWxvdyAkMTAsMDAwCgpBZGRpdGlvbmFsbHksIHdlIHJlbW92ZWQgYSBzcGVjaWZpYyBibG9jayBncm91cCBpbiBOb3J0aCBQaGlsYWRlbHBoaWEgdGhhdCBleGhpYml0ZWQgaW5jb25zaXN0ZW5jaWVzLCB3aXRoIGFuIHVudXN1YWxseSBoaWdoIG1lZGlhbiBob3VzZSB2YWx1ZSAob3ZlciAkODAwLDAwMCkgZGVzcGl0ZSBhIHZlcnkgbG93IG1lZGlhbiBob3VzZWhvbGQgaW5jb21lIChsZXNzIHRoYW4gJDgsMDAwKS4KCkFmdGVyIGRhdGEgY2xlYW5pbmcsIHRoZSBmaW5hbCBkYXRhc2V0IGNvbnRhaW5lZCAxLDcyMCBvYnNlcnZhdGlvbnMuIAoKIyMgRXhwbG9yYXRvcnkgRGF0YSBBbmF5bHNpcwoKIyMjIFN1bW1hcnkgU3RhdGlzdGljcwpXZSB3aWxsIGZpcnN0IGV4YW1pbmUgdGhlIHN1bW1hcnkgc3RhdGlzdGljcyAoICoqbWVhbioqIGFuZCAqKnN0YW5kYXJkIGRldmlhdGlvbiAoU0QpKiopIG9mIGtleSB2YXJpYWJsZXMgaW4gdGhlIGRhdGFzZXQsIGluY2x1ZGluZyB0aGUgZGVwZW5kZW50IHZhcmlhYmxlcyAqTUVESFZBTCogKE1lZGlhbiBIb3VzZSBWYWx1ZSksIGFuZCBwcmVkaWN0b3JzICpOQkVMUE9WMTAwKiAoSG91c2Vob2xkcyBMaXZpbmcgaW4gUG92ZXJ0eSksICpQQ1RCQUNITU9SKiAoJSBvZiBJbmRpdmlkdWFscyB3aXRoIEJhY2hlbG9y4oCZcyBEZWdyZWVzIG9yIEhpZ2hlciksICpQQ1RWQUNBTlQqKCUgb2YgVmFjYW50IEhvdXNlcyksICpQQ1RTSU5HTEVTKiggJSBvZiBTaW5nbGUgSG91c2UgVW5pdHMpLiAKCiAKVGhlICoqbWVhbioqIChcKFxiYXJ7WH1cKSkgcmVwcmVzZW50cyB0aGUgYXZlcmFnZSB2YWx1ZSBvZiBhIHZhcmlhYmxlIGFuZCBpcyBjYWxjdWxhdGVkIGFzOiAgCgokJApcYmFye1h9ID0gXGZyYWN7MX17bn0gXHN1bV97aT0xfV57bn0gWF9pCiQkICAKCndoZXJlOgoKLSBcKFhfaVwpIHJlcHJlc2VudHMgZWFjaCBpbmRpdmlkdWFsIG9ic2VydmF0aW9uICAKLSBcKG5cKSBpcyB0aGUgdG90YWwgbnVtYmVyIG9mIG9ic2VydmF0aW9ucyAgCgpUaGUgbWVhbiBnaXZlcyB1cyBhIHNpbmdsZSByZXByZXNlbnRhdGl2ZSB2YWx1ZSBvZiB0aGUgZGF0YXNldC4gVG8gbWVhc3VyZSB2YXJpYWJpbGl0eSwgd2UgdXNlIHRoZSAqKnN0YW5kYXJkIGRldmlhdGlvbiAoU0QpKiosIHdoaWNoIHF1YW50aWZpZXMgaG93IG11Y2ggdGhlIHZhbHVlcyBpbiBhIGRhdGFzZXQgZGV2aWF0ZSBmcm9tIHRoZSBtZWFuLiBUaGUgZm9ybXVsYSBmb3IgdGhlIHNhbXBsZSBzdGFuZGFyZCBkZXZpYXRpb24gKFwoc1wpKSBpczogIAoKJCQKcyA9IFxzcXJ0e1xmcmFjezF9e24tMX0gXHN1bV97aT0xfV57bn0gXGxlZnQoIFhfaSAtIFxiYXJ7WH0gXHJpZ2h0KV4yfQokJAoKd2hlcmU6CgotIFwoWF9pXCkgcmVwcmVzZW50cyBlYWNoIGluZGl2aWR1YWwgb2JzZXJ2YXRpb24gIAotIFwoXGJhcntYfVwpIGlzIHRoZSBtZWFuIG9mIHRoZSBvYnNlcnZhdGlvbnMgIAotIFwoblwpIGlzIHRoZSB0b3RhbCBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zICAKCkEgbGFyZ2VyIHN0YW5kYXJkIGRldmlhdGlvbiBpbmRpY2F0ZXMgdGhhdCB0aGUgZGF0YSBwb2ludHMgYXJlIG1vcmUgc3ByZWFkIG91dCwgd2hpbGUgYSBzbWFsbGVyIHN0YW5kYXJkIGRldmlhdGlvbiBzdWdnZXN0cyB0aGF0IHRoZSBkYXRhIHBvaW50cyBhcmUgY2xvc2VyIHRvIHRoZSBtZWFuLiAgCgoKIyMjIERpc3RyaWJ1dGlvbnMgCgpXZSB3aWxsIGFsc28gZXhhbWluZSB0aGUgaGlzdG9ncmFtcyBhbmQgYXBwbHkgbG9nIHRyYW5zZm9ybWF0aW9ucyBmb3Iga2V5IHZhcmlhYmxlcyB0byBhc3Nlc3Mgd2hldGhlciB0aGUgdHJhbnNmb3JtZWQgdmFyaWFibGVzIGZvbGxvdyBhIG1vcmUgbm9ybWFsLWxpa2UgZGlzdHJpYnV0aW9uLiAKCioqSGlzdG9ncmFtcyoqIHByb3ZpZGUgYSB2aXN1YWwgcmVwcmVzZW50YXRpb24gb2YgaG93IGEgdmFyaWFibGUncyB2YWx1ZXMgYXJlIGRpc3RyaWJ1dGVkLCBoZWxwaW5nIHRvIGlkZW50aWZ5IHdoZXRoZXIgdGhlIGRhdGEgZm9sbG93cyBhICoqbm9ybWFsIGRpc3RyaWJ1dGlvbioqLCBpcyAqKnJpZ2h0LXNrZXdlZCoqLCBvciAqKmxlZnQtc2tld2VkKiouIExpbmVhciByZWdyZXNzaW9uIG1vZGVsIGFzc3VtZSB0aGF0IHZhcmlhYmxlcyBhcmUgYXBwcm94aW1hdGVseSBub3JtYWxseSBkaXN0cmlidXRlZC4gIAoKLSAqKlgtYXhpczoqKiBUaGUgdmFsdWVzIG9mIHRoZSB2YXJpYWJsZSAoZS5nLiwgaG91c2UgcHJpY2VzLCBpbmNvbWUgbGV2ZWxzKS4gCgotICoqWS1heGlzOioqIFRoZSBmcmVxdWVuY3kgb2Ygb2JzZXJ2YXRpb25zIHdpdGhpbiBlYWNoIGJpbi4gIAoKSWYgdGhlIGhpc3RvZ3JhbSBpcyAqKnJpZ2h0LXNrZXdlZCoqLCBpdCBzdWdnZXN0cyB0aGF0IGEgc21hbGwgbnVtYmVyIG9mIG9ic2VydmF0aW9ucyBoYXZlIHNpZ25pZmljYW50bHkgaGlnaGVyIHZhbHVlcyBjb21wYXJlZCB0byB0aGUgcmVzdC4gRm9yIHZhcmlhYmxlcyBmb2xsb3dpbmcgYSAqKnJpZ2h0LXNrZXdlZCBkaXN0cmlidXRpb24qKiwgd2Ugd2lsbCBhcHBseSBhICoqbG9nIHRyYW5zZm9ybWF0aW9uKiogdG8gdGhlc2UgdmFyaWFibGVzIHRvIGltcHJvdmUgbm9ybWFsaXR5LiBTaW5jZSB0aGUgKipsb2cgdHJhbnNmb3JtYXRpb24qKiBpcyB1bmRlZmluZWQgZm9yIHplcm8gb3IgbmVnYXRpdmUgdmFsdWVzLCB3ZSBtdXN0IGZpcnN0IGNoZWNrIHdoZXRoZXIgYW55IHZhcmlhYmxlIGNvbnRhaW5zIHplcm8uCgotIElmICoqbm8gemVyb3MqKiBwcmVzZW50cywgd2UgYXBwbHkgdGhlIHN0YW5kYXJkIGxvZyB0cmFuc2Zvcm1hdGlvbjogIAokJAogIFgnID0gXGxvZ197MTB9IChYKQokJCAgCi0gSWYgKip6ZXJvcyoqIHByZXNlbnQsIHdlIGFkanVzdCBieSBhZGRpbmcgMSBiZWZvcmUgdGFraW5nIHRoZSBsb2c6ICAKJCQKICBYJyA9IFxsb2dfezEwfSAoWCArIDEpCiQkICAKICBUaGlzIGVuc3VyZXMgdGhhdCBhbGwgdmFsdWVzIHJlbWFpbiBwb3NpdGl2ZSBhbmQgYXZvaWRzIHVuZGVmaW5lZCB2YWx1ZXMuICAKCkJ5IGNvbXBhcmluZyB0aGUgKipvcmlnaW5hbCBoaXN0b2dyYW1zKiogd2l0aCB0aGUgKipsb2ctdHJhbnNmb3JtZWQgaGlzdG9ncmFtcyoqLCB3ZSB3aWxsIGFzc2VzcyB3aGV0aGVyIHRoZSB0cmFuc2Zvcm1hdGlvbiBpbXByb3ZlcyB0aGUgc3VpdGFiaWxpdHkgb2YgdGhlIGRhdGEgZm9yIHByZWRpY3RpdmUgbW9kZWxpbmcuCgoKIyMjIENvcnJlbGF0aW9ucwoKV2Ugd2lsbCBhbmFseXplICoqY29ycmVsYXRpb25zKiogYmV0d2VlbiBwcmVkaWN0b3JzLCB0byBkZXRlY3QgcG90ZW50aWFsICoqbXVsdGljb2xsaW5lYXJpdHkqKiBiZWZvcmUgcHJvY2VlZGluZyB3aXRoIHJlZ3Jlc3Npb24gYW5hbHlzaXMsIHdoaWNoIGNhbiBkaXN0b3J0IG1vZGVsIGludGVycHJldGF0aW9ucy4gIAoKTXVsdGljb2xsaW5lYXJpdHkgb2NjdXJzIHdoZW4gcHJlZGljdG9ycyBhcmUgaGlnaGx5IGNvcnJlbGF0ZWQsIHdoaWNoIGNhbiBsZWFkIHRvIHVuc3RhYmxlIHJlZ3Jlc3Npb24gY29lZmZpY2llbnRzLiBJdCBhbHNvIGluZmxhdGVzIHN0YW5kYXJkIGVycm9ycywgcmVkdWNpbmcgdGhlIHN0YXRpc3RpY2FsIHNpZ25pZmljYW5jZSBvZiBwcmVkaWN0b3JzLCBhbmQgaW5jcmVhc2VzIHRoZSByaXNrIG9mIG92ZXJmaXR0aW5nLCBhcyByZWR1bmRhbnQgdmFyaWFibGVzIGRvIG5vdCBjb250cmlidXRlIG5ldyBpbmZvcm1hdGlvbiB0byB0aGUgbW9kZWwuICAKClRoZSAqKmNvcnJlbGF0aW9uIGNvZWZmaWNpZW50KiogXChyXCkgaXMgY2FsY3VsYXRlZCBhczogIAoKJCQKciA9IFxmcmFje1xzdW1fe2k9MX1ee259ICh4X2kgLSBcYmFye3h9KSh5X2kgLSBcYmFye3l9KX17XHNxcnR7XHN1bV97aT0xfV57bn0gKHhfaSAtIFxiYXJ7eH0pXjIgXHN1bV97aT0xfV57bn0gKHlfaSAtIFxiYXJ7eX0pXjJ9fQokJApJbiBhIG1vcmUgY29uY2lzZSB3YXksIHRoaXMgYWJvdmUgZm9ybXVsYSBpcyBhbHNvIGVxdWl2YWxlbnQgdG8gdGhlIGZvbGxvd2luZzogCgokJApyID0gXGZyYWN7MX17bi0xfSBcc3VtX3tpPTF9XntufSBcbGVmdCggXGZyYWN7eF9pIC0gXGJhcnt4fX17U194fSBccmlnaHQpIFxsZWZ0KCBcZnJhY3t5X2kgLSBcYmFye3l9fXtTX3l9IFxyaWdodCkKJCQKd2hlcmU6ICAKLSBcKFhfaVwpIGFuZCBcKFlfaVwpIGFyZSBpbmRpdmlkdWFsIGRhdGEgcG9pbnRzIGZvciB2YXJpYWJsZXMgXChYXCkgYW5kIFwoWVwpLCByZXNwZWN0aXZlbHkuICAKLSBcKFxiYXJ7WH1cKSBhbmQgXChcYmFye1l9XCkgYXJlIHRoZSAqKm1lYW4gdmFsdWVzKiogb2YgXChYXCkgYW5kIFwoWVwpLiAgCi0gVGhlIG51bWVyYXRvciByZXByZXNlbnRzIHRoZSAqKmNvdmFyaWFuY2UqKiBiZXR3ZWVuIFwoWFwpIGFuZCBcKFlcKSwgd2hpbGUgdGhlIGRlbm9taW5hdG9yICoqbm9ybWFsaXplcyoqIHRoZSB2YWx1ZXMuICAKClRoZSBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBcKHJcKSByYW5nZXMgZnJvbSAqKi0xIHRvIDEqKjogQSB2YWx1ZSBvZiArMSBpbmRpY2F0ZXMgYSBwZXJmZWN0IHBvc2l0aXZlIGxpbmVhciByZWxhdGlvbnNoaXAsIHdoaWxlIGEgdmFsdWUgb2YgLTEgaW5kaWNhdGVzIGEgcGVyZmVjdCBuZWdhdGl2ZSBsaW5lYXIgcmVsYXRpb25zaGlwLiBBIHZhbHVlIG9mIDAgc3VnZ2VzdHMgbm8gbGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSB2YXJpYWJsZXMsIG1lYW5pbmcgY2hhbmdlcyBpbiBvbmUgZG8gbm90IGluZmx1ZW5jZSB0aGUgb3RoZXIuCgojIyBNdWx0aXBsZSBSZWdyZXNzaW9uCkFmdGVyIGdldHRpbmcgYSBnZW5lcmFsIHNlbnNlIG9mIHRoZSBkYXRhLCB3ZSBjb25kdWN0IG11bHRpcGxlIHJlZ3Jlc3Npb24gYW5hbHlzaXMgdG8gZXhhbWluZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIGRlcGVuZGVudCB2YXJpYWJsZSwgKipNZWRpYW4gSG91c2UgVmFsdWUgKE1FREhWQUwpKiosIGFuZCB0aGUgcHJlZGljdG9ycywgKiplZHVjYXRpb24gYXR0YWlubWVudCAoUENUQkFDSE1PUikqKiwgKipudW1iZXIgb2YgSG91c2Vob2xkcyBMaXZpbmcgaW4gUG92ZXJ0eSAoTkJFTFBPVjEwMCkqKiwgKipwZXJjZW50YWdlIG9mIFZhY2FudCBIb3VzZXMgKFBDVFZBQ0FOVCkqKiwgYW5kICoqcGVyY2VudGFnZSBvZiBTaW5nbGUgSG91c2UgVW5pdHMgKFBDVFNJTkdMRVMpKiouIFJlZ3Jlc3Npb24gYW5hbHlzaXMgaXMgYSBzdGF0aXN0aWNhbCBtZXRob2QgdG8gZXhhbWluZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gYSBkZXBlbmRlbnQgdmFyaWFibGUgYW5kIG9uZSBvciBtb3JlIHByZWRpY3RvcnMuIFdpdGggdGhpcyB0eXBlIG9mIGFuYWx5c2lzLCByZXNlYXJjaGVycyBjYW4gaWRlbnRpZnkgdGhlIHN0cmVuZ3RoIGFuZCBkaXJlY3Rpb24gb2YgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHZhcmlhYmxlcywgbWFrZSBwcmVkaWN0aW9ucywgYW5kIGFzc2VzcyB0aGUgc2lnbmlmaWNhbmNlIG9mIHByZWRpY3RvcnMuIFRoZSBtb2RlbCBhbHNvIGVzdGltYXRlcyBjb2VmZmljaWVudHMgZm9yIGVhY2ggcHJlZGljdG9yLCB3aGljaCByZXByZXNlbnQgdGhlIGV4cGVjdGVkIGNoYW5nZSBpbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIGZvciBhIG9uZS11bml0IGNoYW5nZSBpbiB0aGUgcHJlZGljdG9yLCBob2xkaW5nIG90aGVyIHByZWRpY3RvcnMgY29uc3RhbnQuIEZvciB0aGlzIHN0dWR5LCB0aGUgbXVsdGlwbGUgcmVncmVzc2lvbiBtb2RlbCBpcyBmb3JtdWxhdGVkIGFzIGZvbGxvd3M6CiQkClx0ZXh0e0xOTUVESFZBTH0gPSBcYmV0YV8wICsgXGJldGFfMSBcdGV4dHtQQ1RWQUNBTlR9ICsgXGJldGFfMiBcdGV4dHtQQ1RTSU5HTEVTfSArIFxiZXRhXzMgXHRleHR7UENUQkFDSE1PUn0gKyBcYmV0YV80IFx0ZXh0e2xvZyhOQkVMUE9WMTAwKX0gKyBcZXBzaWxvbgokJAp3aGVyZSAqKkxOTUVESFZBTCoqIGlzIHRoZSBsb2ctdHJhbnNmb3JtZWQgbWVkaWFuIGhvdXNlIHZhbHVlLCAqKlBDVFZBQ0FOVCoqIGlzIHRoZSBwcm9wb3J0aW9uIG9mIHZhY2FudCBob3VzaW5nIHVuaXRzICwgKipQQ1RTSU5HTEVTKiogaXMgdGhlIHByb3BvcnRpb24gb2YgdGhlIHNpbmdsZSBmYW1pbHkgaG91c2luZyAsICoqUENUQkFDSE1PUioqIGlzIHRoZSBwZXJjZW50YWdlIG9mIHRoZSByZXNpZGVudHMgaG9sZGluZyBiYWNoZWxvcidzIGRlZ3JlZSBvciBoaWdoZXIsIGFuZCAqKmxvZyhOQkVMUE9WMTAwKSoqICBpcyB0aGUgbG9nLXRyYW5zZm9ybWVkIG51bWJlciBvZiBob3VzZWhvbGRzIGxpdmluZyBiZWxvdyB0aGUgcG92ZXJ0eSBsaW5lLgoKXChcYmV0YV8wXCkgaXMgdGhlIGludGVyY2VwdCwgXChcYmV0YV8xXCksIFwoXGJldGFfMlwpLCBcKFxiZXRhXzNcKSwgYW5kIFwoXGJldGFfNFwpIGFyZSB0aGUgY29lZmZpY2llbnRzIGZvciBlYWNoIHByZWRpY3RvciwgYW5kIFwoXGVwc2lsb25cKSBpcyB0aGUgZXJyb3IgdGVybS4gVGhlIGNvZWZmaWNpZW50IFwoXGJldGFfMVwpLCBcKFxiZXRhXzJcKSwgXChcYmV0YV8zXCksIFwoXGJldGFfNFwpIHJlcHJlc2VudCB0aGUgY2hhbmdlIGluIHRoZSBsb2ctdHJhbnNmb3JtZWQgbWVkaWFuIGhvdXNlIHZhbHVlIGZvciBhIG9uZS11bml0IGNoYW5nZSBpbiB0aGUgY29ycmVzcG9uZGluZyBwcmVkaWN0b3IsIGhvbGRpbmcgb3RoZXIgcHJlZGljdG9ycyBjb25zdGFudC4gVGhlIGVycm9yIHRlcm0gXChcZXBzaWxvblwpIGFjY291bnRzIGZvciB0aGUgdmFyaWFiaWxpdHkgaW4gdGhlIGRlcGVuZGVudCB2YXJpYWJsZSB0aGF0IGlzIG5vdCBleHBsYWluZWQgYnkgdGhlIHByZWRpY3RvcnMuCgojIyMgUmVncmVzc2lvbiBBc3N1bXB0aW9ucwoKVGhlcmUgYXJlIHNldmVyYWwgYXNzdW1wdGlvbnMgYXNzb2NpYXRlZCB3aXRoIHJlZ3Jlc3Npb24gYW5hbHlzaXMgdGhhdCBuZWVkIHRvIGJlIG1ldCBmb3IgdGhlIHJlc3VsdHMgdG8gYmUgdmFsaWQuIFRoZXNlIGFzc3VtcHRpb25zIGluY2x1ZGluZyAqKmxpbmVhcml0eSoqLCAqKmluZGVwZW5kZW5jZSBvZiBvYnNlcnZhdGlvbnMqKiwgKipob21vc2NlZGFzdGljaXR5KiosICoqbm9ybWFsaXR5IG9mIHJlc2lkdWFscyoqLCAqKm5vIG11bHRpY29sbGluZWFyaXR5KiosIGFuZCAqKm5vIGZld2VyIHRoYW4gMTAgb2JzZXJ2YXRpb25zIHBlciBwcmVkaWN0b3JzKiouCgpGaXJzdCwgKipMaW5lYXJpdHkqKiBhc3N1bWVzIHRoYXQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgYW5kIHRoZSBwcmVkaWN0b3JzIGlzIGxpbmVhci4gVG8gdmVyaWZ5IHRoaXMgYXNzdW1wdGlvbiwgd2UgbWFkZSBzY2F0dGVyIHBsb3RzIG9mIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgYWdhaW5zdCBlYWNoIHByZWRpY3Rvci4gSWYgdGhlIHJlbGF0aW9uc2hpcCBhcHBlYXJzIHRvIGJlIGxpbmVhciwgdGhlIGFzc3VtcHRpb25zIHdhcyBtZXQuCgpTZWNvbmQsICoqSW5kZXBlbmRlbmNlIG9mIE9ic2VydmF0aW9ucyoqIGFzc3VtZXMgdGhhdCB0aGUgb2JzZXJ2YXRpb25zIGFyZSBpbmRlcGVuZGVudCBvZiBlYWNoIG90aGVyLiBUaGVyZSBzaG91bGQgYmUgbm8gc3BhdGlhbCBvciB0ZW1wb3JhbCBvciBvdGhlciBmb3JtcyBvZiBkZXBlbmRlbmNlIGluIHRoZSBkYXRhLiAKClRoaXJkLCAqKkhvbW9zY2VkYXN0aWNpdHkqKiBhc3N1bWVzIHRoYXQgdGhlIHZhcmlhbmNlIG9mIHRoZSByZXNpZHVhbHMgXChcZXBzaWxvblwpIGlzIGNvbnN0YW50IHJlZ2FyZGxlc3Mgb2YgdGhlIHZhbHVlcyBvZiBlYWNoIGxldmVsIG9mIHRoZSBwcmVkaWN0b3JzLiBUbyBjaGVjayB0aGlzIGFzc3VtcHRpb24sIHdlIG1hZGUgYSBzY2F0dGVyIHBsb3Qgb2YgdGhlIHN0YW5kYXJkaXplZCByZXNpZHVhbHMgYWdhaW5zdCB0aGUgcHJlZGljdGVkIHZhbHVlcy4gSWYgdGhlIHJlc2lkdWFscyBhcmUgZXZlbmx5IHNwcmVhZCBhcm91bmQgemVybywgdGhlIGFzc3VtcHRpb24gd2FzIG1ldC4gQW55IHBhdHRlcm5zIG1heSBpbmRpY2F0ZSB0aGUgcHJlc2VuY2Ugb2YgaGV0ZXJvc2NlZGFzdGljaXR5LgoKRm91cnRoLCAqKk5vcm1hbGl0eSBvZiBSZXNpZHVhbHMqKiBhc3N1bWVzIHRoYXQgdGhlIHJlc2lkdWFscyBhcmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuIFdlIGV4YW1pbmVkIHRoZSBoaXN0b2dyYW0gb2YgdGhlIHN0YW5kYXJkaXplZCByZXNpZHVhbHMgdG8gY2hlY2sgaWYgdGhleSBhcmUgYXBwcm94aW1hdGVseSBub3JtYWxseSBkaXN0cmlidXRlZC4gSWYgdGhlIGhpc3RvZ3JhbSBpcyBiZWxsLXNoYXBlZCwgdGhlIGFzc3VtcHRpb24gd2FzIG1ldC4KCkZpZnRoLCAqKk5vIE11bHRpY29sbGluZWFyaXR5KiogYXNzdW1lcyB0aGF0IHRoZSBwcmVkaWN0b3JzIGFyZSBub3QgaGlnaGx5IGNvcnJlbGF0ZWQgd2l0aCBlYWNoIG90aGVyLiBXZSBjYWxjdWxhdGVkIHRoZSBjb3JyZWxhdGlvbiBtYXRyaXggb2YgdGhlIHByZWRpY3RvcnMgdG8gY2hlY2sgZm9yIG11bHRpY29sbGluZWFyaXR5LiBJZiB0aGUgY29ycmVsYXRpb24gY29lZmZpY2llbnRzIGFyZSBpcyBub3QgZ3JlYXRlciB0aGFuIDAuOCBvciBsZXNzIHRoYW4gLTAuOCwgdGhlIGFzc3VtcHRpb24gd2FzIG1ldC4KCkZpbmFsbHksICoqTm8gRmV3ZXIgdGhhbiAxMCBPYnNlcnZhdGlvbnMgcGVyIFByZWRpY3RvcioqIGFzc3VtZXMgdGhhdCB0aGVyZSBhcmUgYXQgbGVhc3QgMTAgb2JzZXJ2YXRpb25zIGZvciBlYWNoIHByZWRpY3RvciBpbiB0aGUgbW9kZWwuIFNpbmNlIHRoZXJlIGFyZSBvdmVyIDEsNzAwIG9ic2VydmF0aW9ucyBpbiB0aGUgZGF0YXNldCwgdGhpcyBhc3N1bXB0aW9uIHdhcyBtZXQuCgojIyMgUGFyYW1ldGVyIEVzdGltYXRpb25zCgpBZnRlciB2ZXJpZmluZyB0aGUgYXNzdW1wdGlvbnMgb2YgdGhlIHJlZ3Jlc3Npb24sIHdlIHN0YXJ0IHRoZSByZWdyZXNzaW9uIGFuYWx5c2lzLiBTZXZlcmFsIHBhcmFtZXRlcnMgbmVlZCB0byBlc3RpbWF0ZSBoZXJlOiAKLSBcKCBcYmV0YV8wIFwpLCB3aGljaCBpcyB0aGUgaW50ZXJjZXB0Ci0gXCggXGJldGFfMSwgXGRvdHMsIFxiZXRhX2sgXCksIHdoaWNoIGFyZSBjb2VmZmljaWVudHMgb2YgZWFjaCBpbmRlcGVuZGVudCB2YXJpYWJsZXMKLSBcKCBcc2lnbWFeMiBcKSwgdGhlIHZhcmlhbmNlIG9mIHRoZSBlcnJvciB0ZXJtcywgd2hpY2ggcmVwcmVzZW50cyB0aGUgdmFyaWFiaWxpdHkgaW4gdGhlIGRlcGVuZGVudCB2YXJpYWJsZSB0aGF0IGlzIG5vdCBleHBsYWluZWQgYnkgdGhlIHByZWRpY3RvcnMuCgpUaGUgbGVhc3Qgc3F1YXJlcyBtZXRob2QgZXN0aW1hdGVzIHRoZSBjb2VmZmljaWVudHMgYnkgbWluaW1pemluZyAqKnRoZSBzdW0gb2Ygc3F1YXJlZCBlcnJvcnMgKFNTRSkqKiwgd2hpY2ggaXMgdGhlIHN1bSBvZiB0aGUgc3F1YXJlZCBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSBvYnNlcnZlZCB2YWx1ZXMgYW5kIHRoZSBwcmVkaWN0ZWQgdmFsdWVzLiBUaGUgZm9ybXVsYSBmb3IgU1NFIGlzOgoKJCQKXHRleHR7U1NFfSA9IFxzdW1fe2k9MX1ee259ICh5X2kgLSBcaGF0e3l9X2kpXjIgPSBcc3VtX3tpPTF9XntufSAoeV9pIC0gXGhhdHtcYmV0YX1fMCAtIFxoYXR7XGJldGF9XzEgeF97aTF9IC0gXGRvdHMgLSBcaGF0e1xiZXRhfV9rIHhfe2lrfSleMgokJAp3aGVyZSBcKHlfaVwpIGlzIHRoZSBhY3R1YWwgb3Igb2JzZXJ2ZWQgdmFsdWUsIFwoXGhhdHt5fV9pXCkgaXMgdGhlIHByZWRpY3RlZCB2YWx1ZSwgXChcaGF0e1xiZXRhfV8wLCBcZG90cywgXGhhdHtcYmV0YX1fa1wpIGFyZSB0aGUgZXN0aW1hdGVkIGNvZWZmaWNpZW50cywgYW5kIFwoeF97aTF9LCBcZG90cywgeF97aWt9XCkgYXJlIHRoZSBwcmVkaWN0b3IgdmFsdWVzIGZvciB0aGUgXChpXCktdGggb2JzZXJ2YXRpb24uCgpXaXRoIHRoZSBFcnJvciBTdW0gb2YgU3F1YXJlcyAoU1NFKSBjYWxjdWxhdGVkLCB3ZSBjYW4gZXN0aW1hdGUgdGhlIHZhcmlhbmNlIG9mIHRoZSBlcnJvciB0ZXJtcyBcKFxzaWdtYV4yXCkgdXNpbmcgdGhlIGZvcm11bGE6CgokJApcc2lnbWFeMiA9IFxmcmFje1x0ZXh0e1NTRX19e24gLSAoaysxKX0KJCQKd2hlcmUgXChuXCkgaXMgdGhlIG51bWJlciBvZiBvYnNlcnZhdGlvbnMgYW5kIFwoa1wpIGlzIHRoZSBudW1iZXIgb2YgcHJlZGljdG9ycyBpbiB0aGUgbW9kZWwuCgojIyMgTW9kZWwgRXZhbHVhdGlvbgoKV2UgZXZhbHVhdGVkIHRoZSBtb2RlbCdzIGZpdG5lc3MgdXNpbmcgdGhlIGNvZWZmaWNpZW50IG9mIGRldGVybWluYXRpb24gXChSXjJcKSBhbmQgdGhlIGFkanVzdGVkIFwoUl4yXCkuIFRoZSBjb2VmZmljaWVudCBvZiBkZXRlcm1pbmF0aW9uIFwoUl4yXCkgbWVhc3VyZXMgdGhlIHByb3BvcnRpb24gb2YgdmFyaWFuY2UgaW4gdGhlIGRlcGVuZGVudCB2YXJpYWJsZSB0aGF0IGlzIGV4cGxhaW5lZCBieSB0aGUgcHJlZGljdG9ycy4gVGhlIGFkanVzdGVkIFwoUl4yXCkgYWRqdXN0cyB0aGUgXChSXjJcKSB2YWx1ZSBiYXNlZCBvbiB0aGUgbnVtYmVyIG9mIHByZWRpY3RvcnMsIHdoaWNoIGhlbHAgdG8gcHJvdmlkZSBhIG1vcmUgYWNjdXJhdGUgbWVhc3VyZSBvZiBtb2RlbCBmaXQgZm9yIG11bHRpcGxlIHJlZ3Jlc3Npb24sIGFzIHRoZSBpbmNyZWFzZSB0aGUgbnVtYmVyIG9mIHByZWRpY3RvcnMgY2FuIGFydGlmaWNpYWxseSBpbmZsYXRlIHRoZSBcKFJeMlwpIHZhbHVlLgoKVG8gb2J0YWluIFwoUl4yXCksIFwoU1NUXCkgb3IgdGhlIHRvdGFsIHN1bSBvZiBzcXVhcmVzLCBuZWVkZWQgdG8gYmUgY2FsY3VsYXRlZCBmaXJzdC4gVGhlIFwoU1NUXCkgbWVhc3VyZXMgdGhlIHRvdGFsIHZhcmlhbmNlIGluIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUsIGdpdmVuIGJ5OgokJApTU1QgPSBcc3VtX3tpPTF9XntufSAoeV9pIC0gXGJhcnt5fSleMgokJApXaGVyZSBcKHlfaVwpIGlzIHRoZSBvYnNlcnZlZCB2YWx1ZSwgYW5kIFwoXGJhcnt5fVwpIGlzIHRoZSBtZWFuIG9mIHRoZSBvYnNlcnZlZCB2YWx1ZS4gVGhlbiwgdGhlIFwoUl4yXCkgY2FuIGJlIG9idGFpbmVkIGJ5OgokJApSXjIgPSAxIC0gXGZyYWN7U1NFfXtTU1R9CiQkCkFmdGVyIHRoYXQsIFwoUl4yXCkgaXMgYWRqdXN0ZWQgYXMgZm9sbG93cyBiYXNlZCBvbiB0aGUgbnVtYmVyIG9mIG9ic2VydmF0aW9ucyBcKG5cKSBhbmQgdGhlIG51bWJlciBvZiBwcmVkaWN0b3JzIFwoa1wpOgokJApSXjJfe1x0ZXh0e2Fkan19ID0gMSAtIFxmcmFjeygxIC0gUl4yKShuIC0gMSl9e24gLSBrIC0gMX0KJCQKCiMjIyBIeXBvdGhlc2lzIFRlc3RpbmcKCkluIHRoaXMgYW5hbHlzaXMuIHNldmVyYWwgaHlwb3RoZXNpcyB0ZXN0cyBhcmUgY29uZHVjdGVkIHRvIGRldGVybWluZSB0aGUgc2lnbmlmaWNhbmNlIG9mIHRoZSBtb2RlbCBhbmQgaXRzIHByZWRpY3RvcnMuIFRoZSBvdmVyYWxsIHNpZ25pZmljYW5jZSBvZiB0aGUgbW9kZWwgaXMgYXNzZXNzZWQgdXNpbmcgdGhlIEYtcmF0aW8uIEl0IGNvbXBhcmVzIHRoZSB2YXJpYW5jZSBleHBsYWluZWQgYnkgdGhlIG1vZGVsIHRvIHRoZSB2YXJpYW5jZSBub3QgZXhwbGFpbmVkIGJ5IHRoZSBtb2RlbC5BIGhpZ2hlciBGLXJhdGlvIGluZGljYXRlcyB0aGF0IHRoZSBtb2RlbCBleHBsYWlucyBhIHNpZ25pZmljYW50IGFtb3VudCBvZiB2YXJpYW5jZSBpbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIGNvbXBhcmVkIHRvIHRoZSByZXNpZHVhbCB2YXJpYW5jZS4gCgpUaGUgbnVsbCBoeXBvdGhlc2lzIGFuZCBhbHRlcm5hdGl2ZSBoeXBvdGhlc2lzIGZvciB0aGUgRi1yYXRpbyBhcmUgc3RhdGVkIGFzIGZvbGxvd3M6CgotIFRoZSAqKm51bGwgaHlwb3RoZXNpcyBcKEhfMFwpKiogc3RhdGVzIHRoYXQgYWxsIGNvZWZmaWNpZW50cyBhcmUgZXF1YWwgdG8gemVybywgbWVhbmluZyB0aGF0IHRoZSBwcmVkaWN0b3JzIGRvIG5vdCBleHBsYWluIHRoZSB2YXJpYW5jZSBpbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIChtZWRpYW4gaG91c2UgdmFsdWUpLiBTdGF0ZWQgYXM6CgogICQkCiAgSF8wOiBcYmV0YV8xID0gXGJldGFfMiA9IFxiZXRhXzMgPSBcYmV0YV80ID0gMAogICQkCi0gVGhlICoqYWx0ZXJuYXRpdmUgaHlwb3RoZXNpcyBcKEhfYVwpKiogc3RhdGVzIHRoYXQgYXQgbGVhc3Qgb25lIGNvZWZmaWNpZW50IGlzIG5vdCBlcXVhbCB0byB6ZXJvLiBJbiBvdXIgY2FzZSwgdGhpcyBtZWFucyB0aGF0IGF0IGxlYXN0IG9uZSBwcmVkaWN0b3IgZXhwbGFpbnMgdGhlIHZhcmlhbmNlIGluIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgKG1lZGlhbiBob3VzZSB2YWx1ZSkuIFN0YXRlZCBhczoKICAkJAogIEhfYTogXHRleHR7QXQgbGVhc3Qgb25lIH0gXGJldGFfaSBcbmVxIDAKICAkJAoKV2UgYWxzbyBjb25kdWN0IGEgdC10ZXN0IHRvIGRldGVybWluZSB0aGUgc2lnbmlmaWNhbmNlIG9mIGVhY2ggaW5kaXZpZHVhbCBwcmVkaWN0b3IgaW4gdGhlIG1vZGVsOgoKLSBUaGUgKipudWxsIGh5cG90aGVzaXMgXChIX3swaX1cKSoqIHN0YXRlcyB0aGF0IHRoZSBjb2VmZmljaWVudCBmb3IgdGhlIHByZWRpY3RvciBpIGlzIGVxdWFsIHRvIHplcm8sIG1lYW5pbmcgdGhhdCB0aGUgcHJlZGljdG9yIGRvZXMgbm90IGV4cGxhaW4gdGhlIHZhcmlhbmNlIGluIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgKG1lZGlhbiBob3VzZSB2YWx1ZSkuIFN0YXRlZCBhczoKCiAgJCQKICBIX3swaX06IFxiZXRhX2kgPSAwCiAgJCQKICAKLSBUaGUgKiphbHRlcm5hdGl2ZSBoeXBvdGhlc2lzIFwoSF97YWl9XCkqKiBzdGF0ZXMgdGhhdCB0aGUgY29lZmZpY2llbnQgZm9yIHRoZSBwcmVkaWN0b3IgaSBpcyBub3QgZXF1YWwgdG8gemVybywgbWVhbmluZyB0aGF0IHRoZSBwcmVkaWN0b3IgZXhwbGFpbnMgdGhlIHZhcmlhbmNlIGluIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgKG1lZGlhbiBob3VzZSB2YWx1ZSkuIFN0YXRlZCBhczoKICAKICAkJAogIEhfe2FpfTogXGJldGFfaSBcbmVxIDAKICAkJAogIAojIyBBZGRpdGlvbmFsIEFuYWx5c2lzCgojIyMgU3RlcHdpc2UgUmVncmVzc2lvbgoKSW4gYWRkaXRpb24gdG8gdGhlIG11bHRpcGxlIHJlZ3Jlc3Npb24gYW5hbHlzaXMsIHdlIGNvbmR1Y3Qgc3RlcHdpc2UgcmVncmVzc2lvbiBhbmFseXNpcyB0byBpZGVudGlmeSB0aGUgbW9zdCBzaWduaWZpY2FudCBwcmVkaWN0b3JzIG9mIG1lZGlhbiBob3VzZSB2YWx1ZXMgaW4gUGhpbGFkZWxwaGlhLiBTdGVwd2lzZSByZWdyZXNzaW9uIGlzIGEgbWV0aG9kIHRoYXQgYXV0b21hdGljYWxseSBzZWxlY3RzIHRoZSBiZXN0IHN1YnNldCBvZiBwcmVkaWN0b3JzIGZvciB0aGUgbW9kZWwuIEl0IGludm9sdmVzIGFkZGluZyBvciByZW1vdmluZyBwcmVkaWN0b3JzIGJhc2VkIG9uIHRoZWlyIHN0YXRpc3RpY2FsIHNpZ25pZmljYW5jZSAoUC12YWx1ZSkgYW5kIHRoZSBBSUMgKEFrYWlrZSBJbmZvcm1hdGlvbiBDcml0ZXJpb24pLiBUaGUgc3RlcHdpc2UgcmVncmVzc2lvbiBhbmFseXNpcyB3aWxsIGhlbHAgdXMgaWRlbnRpZnkgdGhlIG1vc3QgaW1wb3J0YW50IHByZWRpY3RvcnMgYW5kIGltcHJvdmUgdGhlIG92ZXJhbGwgbW9kZWwgZml0cy4KCkhvd2V2ZXIsIHRoZXJlIGFyZSBzZXZlcmFsIGxpbWl0YXRpb25zIHRvIHN0ZXB3aXNlIHJlZ3Jlc3Npb24uIEZpcnN0LCB0aGUgZmluYWwgc3RlcHdpc2UgcmVncmVzc2lvbiBtb2RlbCBpcyBub3QgZ3VhcmFudGVlZCB0byBiZSBvcHRpbWFsIGluIGFueSBzcGVjaWZpYyBzZW5zZS4gVGhlcmUgbWF5IGJlIG90aGVyIG1vZGVscyB0aGF0IGFyZSBhcyBnb29kIGFzLCBvciBldmVuIGJldHRlciB0aGFuIHRoZSBvbmUgc2VsZWN0ZWQgYnkgc3RlcHdpc2UgcmVncmVzc2lvbiwgYnV0IHRoZSBwcm9jZWR1cmUgb25seSB5ZWlsZHMgYSBzaW5nbGUgbW9kZWwuIFNlY29uZCwgdGhlIHN0ZXB3aXNlIHJlZ3Jlc3Npb24gZG9lcyB0YWtlIGludG8gYWNjb3VudCByZXNlYXJjaGVycycga25vd2xlZGdlIGFib3V0IHRoZSBwcmVkaWN0b3JzLiBJbXBvcnRhbnQgdmFyaWFibGVzIG1heSBiZSBleGNsdWRlIGZyb20gdGhlIG1vZGVsIGlmIHRoZXkgYXJlIG5vdCBpbmNsdWRlZCBpbiB0aGUgaW5pdGlhbGx5LiBNb3Jlb3ZlciwgVGhpcyBtZXRob2QgYWxzbyBydW5zIHRoZSByaXNrIG9mIFR5cGUgSSBhbmQgVHlwZSBJSSBlcnJvcnPigJRtZWFuaW5nIGl0IG1heSBpbmNsdWRlIHVuaW1wb3J0YW50IHZhcmlhYmxlcyBvciBleGNsdWRlIGltcG9ydGFudCBvbmVzLiAKCiMjIyBDcm9zcy1WYWxpZGF0aW9uCgpUbyBldmFsdWF0ZSB0aGUgcGVyZm9ybWFuY2Ugb2YgdGhlIHJlZ3Jlc3Npb24gbW9kZWwsIHdlIGNvbmR1Y3QgSy1mb2xkIGNyb3NzLXZhbGlkYXRpb24uIENyb3NzLXZhbGlkYXRpb24gaXMgYSB0ZWNobmlxdWUgdXNlZCB0byBldmx1YXRlIHRoZSBwZXJmb3JtYW5jZSBvZiB0aGUgcHJlZGljdGl2ZSBtb2RlbHMuIEluIEstZm9sZCBDcm9zcy1WYWxpZGF0aW9uLCB0aGUgZGF0YXNldCBpcyByYW5kb21seSBkaXZpZGVkIGludG8gSyBlcXVhbC1zaXplZCBmb2xkcy4gVGhlIG1vZGVsIGlzIHRyYWluZWQgb24gSy0xIGZvbGRzIGFuZCB0ZXN0ZWQgb24gdGhlIHJlbWFpbmluZyBmb2xkLiBUaGlzIHByb2Nlc3MgaXMgcmVwZWF0ZWQgSyB0aW1lcywgd2l0aCBlYWNoIGZvbGQgc2VydmluZyBhcyB0aGUgdGVzdCBzZXQgZXhhY3RseSBvbmNlLiBUaGUgYXZlcmFnZSBwZXJmb3JtYW5jZSBhY3Jvc3MgYWxsIEsgZm9sZHMgaXMgdGhlbiBjYWxjdWxhdGVkLiBDcm9zcy12YWxpZGF0aW9uIGhlbHBzIHRvIGFzc2VzcyB0aGUgbW9kZWwncyBnZW5lcmFsaXphdGlvbiBwZXJmb3JtYW5jZSBhbmQgcmVkdWNlIHRoZSByaXNrIG9mIG92ZXJmaXR0aW5nLgoKSW4gb3VyIGFuYWx5c2lzLCB3ZSB1c2VkIEs9NSwgd2hpY2ggaXMgYSBjb21tb24gY2hvaWNlIGZvciBjcm9zcy12YWxpZGF0aW9uLiBUaGUgcm9vdCBtZWFuIHNxdWFyZWQgZXJyb3IgKFJNU0UpIGlzIHVzZWQgdG8gY29tcGFyZSB0aGUgcGVyZm9ybWFuY2Ugb2YgZGlmZmVyZW50IG1vZGVscy4gVGhlIFJNU0UgbWVhc3VyZXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgcHJlZGljdGVkIHZhbHVlcyBhbmQgdGhlIGFjdHVhbCB2YWx1ZXMuIEEgbG93ZXIgdmFsdWUgb2YgUk1TRSBpbmRpY2F0ZXMgYSBiZXR0ZXIgcHJlZGljdGl2ZSBtb2RlbC4KClRoZSBtZWFuIHNxdWFyZSBlcnJvcnMgaXMgY2FsY3VsYXRlZCBhcyBmb2xsb3dzOgokJCAKXHRleHR7TVNFfSA9IFxmcmFjezF9e259IFxzdW1fe2k9MX1ee259ICh5X2kgLSBcaGF0e3l9X2kpXjIgCiQkCkFuZCB0aGUgcm9vdCBtZWFuIHNxdWFyZSBlcnJvcnMgKFJNU0UpIGlzIHRoZSBzcXVhcmUgcm9vdCBvZiB0aGUgbWVhbiBzcXVhcmUgZXJyb3JzIChNU0UpOgokJApcdGV4dHtSTVNFfSA9IFxzcXJ0e1x0ZXh0e01TRX19CiQkCgojIyBTb2Z0d2FyZSBhbmQgUGFja2FnZXMKCkluIHRoaXMgYW5hbHlzaXMsIHdlIHV0aWxpemUgdGhlIFIgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2UsIGEgcHJvZmVzc2lvbmFsIHN0YXRpc3RpY2FsIHNvZnR3YXJlIHdpZGVseSB1c2VkIGZvciBkYXRhIGFuYWx5c2lzIGFuZCB2aXN1YWxpemF0aW9uLlRoZSBmb2xsb3dpbmcgbGlicmFyaWVzIGFuZCBwYWNrYWdlcyBoYXZlIGJlZW4gZW1wbG95ZWQgdG8gY29uZHVjdCB0aGUgYW5hbHlzaXM6CgotIGB0aWR5dmVyc2VgOiBBIGNvbGxlY3Rpb24gb2YgUiBwYWNrYWdlcyBmb3IgZGF0YSBtYW5pcHVsYXRpb24gYW5kIHZpc3VhbGl6YXRpb24uCi0gYHNmYDogQSBwYWNrYWdlIGZvciBzcGF0aWFsIGRhdGEgcHJvY2Vzc2luZywgZXNwZWNpYWxseSBmb3IgaGFuZGxpbmcgc2hhcGVmaWxlcy4KLSBgZ2dwbG90MmA6IEEgcG9wdWxhciB2aXN1YWxpemF0aW9uIHBhY2thZ2UgZm9yIGNyZWF0aW5nIGhpZ2gtcXVhbGl0eSBtYXAgYW5kIGNoYXJ0cywgcGFydCBvZiB0aGUgYHRpZHl2ZXJzZWAgY29sbGVjdGlvbi4KLSBgZ2djb3JycGxvdGA6IEEgcGFja2FnZSBkZXNpZ25hdGVkIHRvICB2aXN1YWxpemUgY29ycmVsYXRpb24gbWF0cmljZXMgdXNpbmcgYGdncGxvdDJgLgotIGBwYXRjaHdvcmtgOiBBIHBhY2thZ2UgZm9yIGNvbWJpbmluZyBtdWx0aXBsZSBnZ3Bsb3QyIHBsb3RzIGludG8gYSBzaW5nbGUgcGxvdC4KLSBgTUFTU2A6IEEgcGFja2FnZSBwcm92aWRlcyBtdWx0aXBsZSBmdW5jdGlvbnMgYW5kIGRhdGFzZXRzIGZvciBzdGF0aXN0aWNhbCBhbmFseXNpcywgaW5jbHVkaW5nIGxpbmVhciBtb2RlbHMuIAotIGBjYXJldGA6IEEgcGFja2FnZSBmb3IgY3JlYXRpbmcgcHJlZGljdGl2ZSBtb2RlbHMgYW5kIGNvbmR1Y3RpbmcgbWFjaGluZSBsZWFybmluZyB0YXNrcywgdXNlZCBpbiBjcm9zcy12YWxpZGF0aW9uIGFuZCBrLWZvbGQgYW5hbHlzaXMuCi0gYGthYmxlRXh0cmFgOiBBIHBhY2thZ2UgZm9yIGNyZWF0aW5nIHRhYmxlcyB3aXRoIGFkdmFuY2VkIGZvcm1hdHRpbmcgb3B0aW9ucy4KCiMgUmVzdWx0cwoKIyMgRXhwbG9yYXRvcnkgUmVzdWx0cyAKClRoZSB0YWJsZSBiZWxvdyBwcmVzZW50cyB0aGUgc3VtbWFyeSBzdGF0aXN0aWNzIGZvciB0aGUga2V5IHZhcmlhYmxlcywgYW4gb3ZlcnZpZXcgb2YgdGhlIGNlbnRyYWwgdGVuZGVuY3kgYW5kIHZhcmlhYmlsaXR5LiBUaGUgZGVwZW5kZW50IHZhcmlhYmxlICptZWRpYW4gaG91c2UgdmFsdWUqIGhhcyBhIG1lYW4gb2YgNjYsMjg3LjczLCBpbmRpY2F0aW5nIHRoYXQgdGhlIGF2ZXJhZ2UgbWVkaWFuIGhvdXNlIHZhbHVlIGJ5IGNlbnN1cyB0cmFjdCBpbiBQaGlsYWRlbHBoaWEgaXMgYXBwcm94aW1hdGVseSA2NiwyODcuNzMgZG9sbGFyLiBUaGUgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIDYwLDAwNi4wOCBkb2xsYXIgc3VnZ2VzdHMgdGhhdCBob3VzZSB2YWx1ZXMgZXhoaWJpdCBzaWduaWZpY2FudCB2YXJpYWJpbGl0eSBhY3Jvc3MgY2Vuc3VzIHRyYWN0cy4KCkZvciB0aGUgcHJlZGljdG9yIHZhcmlhYmxlcywgYWxsIGhhdmUgc3RhbmRhcmQgZGV2aWF0aW9ucyBjbG9zZSB0byBvciBncmVhdGVyIHRoYW4gdGhlIG1lYW4sIGluZGljYXRpbmcgbGFyZ2UgZGlmZmVyZW5jZXMgaW4gZWR1Y2F0aW9uYWwgYXR0YWlubWVudCwgZWNvbm9taWMgc3RhdHVzLCBob3VzaW5nIG9jY3VwYW5jeSwgYW5kIGhvdXNpbmcgc3RydWN0dXJlIGNvbXBvc2l0aW9uIGFjcm9zcyBQaGlsYWRlbHBoaWEncyBjZW5zdXMgYmxvY2sgZ3JvdXBzLgoKYGBge3Igc3VtbWFyeSBzdGF0cywgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KZGVwZW5kZW50X3ZhciA8LSAiTUVESFZBTCIKCnByZWRpY3RvcnMgPC0gYygiUENUQkFDSE1PUiIsICJOQkVMUE9WMTAwIiwgIlBDVFZBQ0FOVCIsICJQQ1RTSU5HTEVTIikKCnN1bW1hcnlfc3RhdHMgPC0gZGF0YSAlPiUKICBkcGx5cjo6c2VsZWN0KGFsbF9vZihjKGRlcGVuZGVudF92YXIsIHByZWRpY3RvcnMpKSkgJT4lCiAgc3VtbWFyaXNlX2FsbChsaXN0KE1lYW4gPSBtZWFuLCBTRCA9IHNkKSwgbmEucm0gPSBUUlVFKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGV2ZXJ5dGhpbmcoKSwgbmFtZXNfdG8gPSAiVmFyaWFibGUiLCB2YWx1ZXNfdG8gPSAiVmFsdWUiKSAlPiUKICBzZXBhcmF0ZShWYXJpYWJsZSwgaW50byA9IGMoIlZhcmlhYmxlIiwgIlN0YXQiKSwgc2VwID0gIl8iKSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gU3RhdCwgdmFsdWVzX2Zyb20gPSBWYWx1ZSkKCgoKc3VtbWFyeV9zdGF0cyRWYXJpYWJsZSA8LSByZWNvZGUoc3VtbWFyeV9zdGF0cyRWYXJpYWJsZSwKICAiTUVESFZBTCIgPSAiTWVkaWFuIEhvdXNlIFZhbHVlIiwKICAiTkJFTFBPVjEwMCIgPSAiIyBIb3VzZWhvbGRzIExpdmluZyBpbiBQb3ZlcnR5IiwKICAiUENUQkFDSE1PUiIgPSAiJSBvZiBJbmRpdmlkdWFscyB3aXRoIEJhY2hlbG9y4oCZcyBEZWdyZWVzIG9yIEhpZ2hlciIsCiAgIlBDVFZBQ0FOVCIgPSAiJSBvZiBWYWNhbnQgSG91c2VzIiwKICAiUENUU0lOR0xFUyIgPSAiJSBvZiBTaW5nbGUgSG91c2UgVW5pdHMiCikKCgoKc3VtbWFyeV9zdGF0cyA8LSBzdW1tYXJ5X3N0YXRzICU+JQogIG11dGF0ZSgKICAgIE1lYW4gPSByb3VuZChNZWFuLCAyKSwKICAgIFNEID0gcm91bmQoU0QsIDIpCiAgKQoKc3VtbWFyeV9zdGF0cyA8LSBzdW1tYXJ5X3N0YXRzICU+JQogIGFycmFuZ2UoVmFyaWFibGUgPT0gIk1lZGlhbiBIb3VzZSBWYWx1ZSIpCgpwcmVkaWN0b3Jfcm93cyA8LSB3aGljaChzdW1tYXJ5X3N0YXRzJFZhcmlhYmxlICE9ICJNZWRpYW4gSG91c2UgVmFsdWUiKQpkZXBlbmRlbnRfcm93cyA8LSB3aGljaChzdW1tYXJ5X3N0YXRzJFZhcmlhYmxlID09ICJNZWRpYW4gSG91c2UgVmFsdWUiKQoKIyBEZXRlcm1pbmUgdGhlIHN0YXJ0IGFuZCBlbmQgcm93cyBmb3IgZWFjaCBncm91cApzdGFydF9wcmVkIDwtIG1pbihwcmVkaWN0b3Jfcm93cykKZW5kX3ByZWQgICA8LSBtYXgocHJlZGljdG9yX3Jvd3MpCnN0YXJ0X2RlcCAgPC0gbWluKGRlcGVuZGVudF9yb3dzKQplbmRfZGVwICAgIDwtIG1heChkZXBlbmRlbnRfcm93cykKCiMgQ3JlYXRlIHRoZSB0YWJsZSB1c2luZyBrYWJsZSBhbmQgYWRkIGV4dHJhIGZvcm1hdHRpbmcKa2FibGUoc3VtbWFyeV9zdGF0cywgY2FwdGlvbiA9ICJTdW1tYXJ5IFN0YXRpc3RpY3MiLCAKICAgICAgYWxpZ24gPSBjKCJsIiwgImwiLCAibCIpLCBib29rdGFicyA9IFRSVUUsIGVzY2FwZSA9IEZBTFNFICkgJT4lCiAgYWRkX2hlYWRlcl9hYm92ZShjKCIgIiA9IDEsICJTdGF0aXN0aWNzIiA9IDIpKSAlPiUKICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSkgJT4lCiAgZ3JvdXBfcm93cygiUHJlZGljdG9ycyIsIHN0YXJ0X3ByZWQsIGVuZF9wcmVkKSAlPiUKICBncm91cF9yb3dzKCJEZXBlbmRlbnQgVmFyaWFibGUiLCBzdGFydF9kZXAsIGVuZF9kZXApJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBUUlVFKQoKYGBgCgoKIyMjIEhpc3RvZ3JhbSBEaXN0cmlidXRpb24KCk9uZSBvZiB0aGUgYXNzdW1wdGlvbnMgb2YgT0xTIHJlZ3Jlc3Npb24gaXMgdGhhdCB2YXJpYWJsZXMgZm9sbG93IGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4gVG8gYXNzZXNzIHRoZSBkaXN0cmlidXRpb24gb2Yga2V5IHZhcmlhYmxlcywgdGhlaXIgaGlzdG9ncmFtcyBhcmUgcHJlc2VudGVkIGJlbG93LiBBcyBzZWVuIGluIHRoZSBwbG90cywgYWxsIGtleSB2YXJpYWJsZXMgZXhoaWJpdCBsZWZ0LXNrZXduZXNzLCBtZWFuaW5nIHRoZWlyIGRpc3RyaWJ1dGlvbnMgYXJlIHJpZ2h0LXNrZXdlZCAocG9zaXRpdmVseSBza2V3ZWQpLCB3aXRoIGEgY29uY2VudHJhdGlvbiBvZiBzbWFsbGVyIHZhbHVlcyBhbmQgYSBsb25nIHJpZ2h0IHRhaWwuCgpgYGB7ciwgaW5jbHVkZT1GQUxTRX0KI2NoZWNrIDAKY29sdW1uc190b19jaGVjayA8LSBjKGRlcGVuZGVudF92YXIsIHByZWRpY3RvcnMpCgp6ZXJvX2NvdW50cyA8LSBzYXBwbHkoZGF0YVtjb2x1bW5zX3RvX2NoZWNrXSwgZnVuY3Rpb24oeCkgc3VtKHggPT0gMCwgbmEucm0gPSBUUlVFKSkKCnplcm9fY291bnRzW3plcm9fY291bnRzID4gMF0KCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTksIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9Cmxvbmdlcl92ZXJzaW9uPC0gZGF0YSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGMoIk1FREhWQUwiLCAiUENUQkFDSE1PUiIsICJOQkVMUE9WMTAwIiwgIlBDVFZBQ0FOVCIsICJQQ1RTSU5HTEVTIiksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIlZhcmlhYmxlIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIlZhbHVlIikKCmdncGxvdChsb25nZXJfdmVyc2lvbixhZXMoeCA9IFZhbHVlKSkgKwogIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5jb3VudC4uKSwgZmlsbCA9ICJibGFjayIsIGFscGhhID0gMC43KSArICAKICBmYWNldF93cmFwKH5WYXJpYWJsZSwgc2NhbGVzID0gImZyZWUiLCBuY29sID0gMywgbGFiZWxsZXIgPSBhc19sYWJlbGxlcihjKAogICAgIk1FREhWQUwiID0gIk1lZGlhbiBIb3VzZSBWYWx1ZSIsCiAgICAiUENUQkFDSE1PUiIgPSAiJSB3aXRoIEJhY2hlbG9y4oCZcyBEZWdyZWVzIG9yIEhpZ2hlciIsCiAgICAiTkJFTFBPVjEwMCIgPSAiIyBIb3VzZWhvbGRzIExpdmluZyBpbiBQb3ZlcnR5IiwKICAgICJQQ1RWQUNBTlQiID0gIiUgb2YgVmFjYW50IEhvdXNlcyIsCiAgICAiUENUU0lOR0xFUyIgPSAiJSBvZiBTaW5nbGUgSG91c2UgVW5pdHMiCiAgKSkpICsgIAogIGxhYnMoeCA9ICJWYWx1ZSIsIHkgPSAiQ291bnQiLCB0aXRsZSA9ICJIaXN0b2dyYW1zIG9mIERlcGVuZGVudCBhbmQgUHJlZGljdG9yIFZhcmlhYmxlcyIpICsKICB0aGVtZV9saWdodCgpICsgICAKICB0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LGZhY2UgPSAiaXRhbGljIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLCAKICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT02KSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT02KSwgCiAgICAgICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT04KSkKYGBgCgpUbyBtZWV0IHRoZSBub3JtYWxpdHkgYXNzdW1wdGlvbiBvZiBPTFMsIGxvZyB0cmFuc2Zvcm1hdGlvbiBpcyBhcHBsaWVkIHdoZXJlIG5lY2Vzc2FyeSB0byBpbXByb3ZlIGRpc3RyaWJ1dGlvbmFsIHN5bW1ldHJ5LiBUaGlzIHRyYW5zZm9ybWF0aW9uIGhlbHBzIG5vcm1hbGl6ZSB0aGUgZGlzdHJpYnV0aW9ucywgbWFraW5nIHRoZW0gbW9yZSBzdWl0YWJsZSBmb3IgcmVncmVzc2lvbiBhbmFseXNpcy4gVGhlIGhpc3RvZ3JhbXMgb2YgdGhlIGxvZy10cmFuc2Zvcm1lZCB2YXJpYWJsZXMgaW5kaWNhdGUgYSBtb3JlIG5vcm1hbC1saWtlIGRpc3RyaWJ1dGlvbi4gSG93ZXZlciwgc29tZSBzbGlnaHQgc2tld25lc3MgcmVtYWluczogdGhlIGRlcGVuZGVudCB2YXJpYWJsZSAoKkxvZyBNZWRpYW4gSG91c2UgVmFsdWUqKSBhbmQgdGhlIHByZWRpY3RvciAoKkxvZyAlIFNpbmdsZSBIb3VzZSBWYWx1ZSopIGFyZSBzbGlnaHRseSBsZWZ0LXNrZXdlZCwgd2hpbGUgdGhlIHByZWRpY3RvcnMgKkxvZyAlIEhvdXNlaG9sZHMgaW4gUG92ZXJ0eSogYW5kICpMb2cgJSBWYWNhbnQgSG91c2VzKiBhcmUgc2xpZ2h0bHkgcmlnaHQtc2tld2VkLgpgYGB7cn0KZGF0YSA8LSBkYXRhICU+JQogIG11dGF0ZSgKICAgIExOTUVESFZBTCA9IGxvZyhNRURIVkFMKSwKICAgIExOUENUQkFDSE1PUiA9IGxvZygxK1BDVEJBQ0hNT1IpLAogICAgTE5OQkVMUE9WMTAwID0gbG9nKDErTkJFTFBPVjEwMCksCiAgICBMTlBDVFZBQ0FOVCA9IGxvZygxK1BDVFZBQ0FOVCksCiAgICBMTlBDVFNJTkdMRVMgPSBsb2coMStQQ1RTSU5HTEVTKQogICkKYGBgCgpgYGB7ciwgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9OSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KbG9uZ2VyX3ZlcnNpb24yIDwtIGRhdGEgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKExOTUVESFZBTCwgTE5QQ1RCQUNITU9SICxMTk5CRUxQT1YxMDAsTE5QQ1RWQUNBTlQsIExOUENUU0lOR0xFUyksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIlZhcmlhYmxlIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIlZhbHVlIikKCmdncGxvdChsb25nZXJfdmVyc2lvbjIsYWVzKHggPSBWYWx1ZSkpICsKICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uY291bnQuLiksIGZpbGwgPSAicmVkIiwgYWxwaGEgPSAwLjcpICsgIAogIGZhY2V0X3dyYXAoflZhcmlhYmxlLCBzY2FsZXMgPSAiZnJlZSIsIG5jb2wgPSAzLCBsYWJlbGxlciA9IGFzX2xhYmVsbGVyKGMoCiAgICAiTE5NRURIVkFMIiA9ICJMb2cgTWVkaWFuIEhvdXNlIFZhbHVlIiwKICAgICJMTlBDVEJBQ0hNT1IiID0gIkxvZyAlIHdpdGggQmFjaGVsb3LigJlzIERlZ3JlZSIsCiAgICAiTE5OQkVMUE9WMTAwIiA9ICJMb2cgIyBIb3VzZWhvbGRzIGluIFBvdmVydHkiLAogICAgIkxOUENUVkFDQU5UIiA9ICJMb2cgJSBWYWNhbnQgSG91c2VzIiwKICAgICJMTlBDVFNJTkdMRVMiID0gIkxvZyAlIFNpbmdsZSBIb3VzZSBVbml0cyIKICApKSkgKyAgCiAgbGFicyh4ID0gIlZhbHVlIiwgeSA9ICJDb3VudCIsIHRpdGxlID0gIkhpc3RvZ3JhbXMgb2YgRGVwZW5kZW50IGFuZCBsb2cgdHJhbnNmb3JtZWQgUHJlZGljdG9yIFZhcmlhYmxlcyIpICsKICB0aGVtZV9saWdodCgpICsgICAKICB0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LGZhY2UgPSAiaXRhbGljIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLCAKICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT02KSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT02KSwgCiAgICAgICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT04KSkKYGBgCgoKT3RoZXIgcmVncmVzc2lvbiBhc3N1bXB0aW9ucyB3aWxsIGJlIGFzc2Vzc2VkIHNlcGFyYXRlbHkgaW4gdGhlIFJlZ3Jlc3Npb24gQXNzdW1wdGlvbiBDaGVja3Mgc2VjdGlvbiBsYXRlci4KCiMjIyBDaG9yb3BsZXRoIE1hcHMKCkxpbmVhcml0eSBhc3N1bWVzIHRoYXQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgYW5kIHRoZSBwcmVkaWN0b3JzIGlzIGxpbmVhci4gVG8gZXhhbWluZSB0aGlzIHJlbGF0aW9uc2hpcCwgd2UgYW5hbHl6ZSB0aGUgc3BhdGlhbCBkaXN0cmlidXRpb24gb2Yga2V5IHZhcmlhYmxlcy4gQ2VydGFpbiBwcmVkaWN0b3IgbWFwcyBleGhpYml0IHBhdHRlcm5zIHNpbWlsYXIgdG8gdGhlIGRlcGVuZGVudCB2YXJpYWJsZSwgc3VnZ2VzdGluZyBhIHN0cm9uZyBwb3RlbnRpYWwgcmVsYXRpb25zaGlwLgoKQmVsb3cgaXMgdGhlIGNob3JvcGxldGggbWFwIG9mIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUsICpMb2cgVHJhbnNmb3JtZWQgTWVkaWFuIEhvdXNlIFZhbHVlKi4gSXQgcmV2ZWFscyB0aGF0IGNlbnRyYWwgY2l0eSBhcmVhcyBhbmQgR2VybWFudG93bi9DaGVzdG51dCBIaWxsIGhhdmUgaGlnaGVyIG1lZGlhbiBob3VzZSB2YWx1ZXMsIHdoaWxlIE5vcnRoIFBoaWxhZGVscGhpYSBoYXMgbG93ZXIgdmFsdWVzLiAgCgoKYGBge3IsZmlnLmhlaWdodD03LCBmaWcud2lkdGg9OSx3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpnZ3Bsb3Qoc2hhcGUpICsKICBnZW9tX3NmKGFlcyhmaWxsID0gTE5NRURIVkFMKSwgY29sb3IgPSAidHJhbnNwYXJlbnQiKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3JzID0gYygiI2ZmZjBmMyIsICIjYTQxMzNjIiksIAogICAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAiTE5NRURIVkFMIiwgCiAgICAgICAgICAgICAgICAgICAgICAgbmEudmFsdWUgPSAidHJhbnNwYXJlbnQiKSArIAogIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksIGZhY2UgPSAiaXRhbGljIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJncmV5IiwgZmlsbCA9IE5BLCBzaXplID0gMC44KSkgKwogIGxhYnModGl0bGUgPSAiTG9nIFRyYW5zZm9ybWVkIE1lZGlhbiBIb3VzZSBWYWx1ZSIpCmBgYAoKVG8gdW5kZXJzdGFuZCB0aGUgc3BhdGlhbCByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIGFuZCBwcmVkaWN0b3JzLCB3ZSBwcmVzZW50IGZvdXIga2V5IHByZWRpY3RvciBtYXBzIGJlbG93IGFzIHdlbGwuIAoKYGBge3IsIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD0xNSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0Kc2hwZV9sb25nZXI8LSBzaGFwZSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGMoIlBDVFZBQ0FOVCIsICJQQ1RTSU5HTEVTIiwgIlBDVEJBQ0hNT1IiLCAiTE5OQkVMUE9WIiksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIlZhcmlhYmxlIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIlZhbHVlIikKY3VzdG9tX3RpdGxlcyA8LSBjKAogIFBDVFZBQ0FOVCAgID0gIlBlcmNlbnQgb2YgVmFjYW50IEhvdXNlcyIsCiAgUENUU0lOR0xFUyAgPSAiUGVyY2VudCBvZiBTaW5nbGUgSG91c2UgVW5pdHMiLAogIFBDVEJBQ0hNT1IgID0gIlBlcmNlbnQgb2YgQmFjaGVsb3IncyBEZWdyZWUgb3IgSGlnaGVyIiwKICBMTk5CRUxQT1YgICA9ICJMb2dnZWQgVHJhbnNmb3JtZWQgUG92ZXJ0eSBSYXRlIgopCgoKCnBsb3RfbGlzdCA8LSBsYXBwbHkodW5pcXVlKHNocGVfbG9uZ2VyJFZhcmlhYmxlKSwgZnVuY3Rpb24odmFyX25hbWUpIHsKICBkYXRhX3N1YnNldCA8LSBzdWJzZXQoc2hwZV9sb25nZXIsIFZhcmlhYmxlID09IHZhcl9uYW1lKQogIAogIGdncGxvdChkYXRhX3N1YnNldCkgKwogICAgZ2VvbV9zZihhZXMoZmlsbCA9IFZhbHVlKSwgY29sb3IgPSAidHJhbnNwYXJlbnQiKSArCiAgICBzY2FsZV9maWxsX2dyYWRpZW50bigKICAgICAgY29sb3JzID0gYygiI2ZmZjBmMyIsICIjYTQxMzNjIiksCiAgICAgIG5hbWUgPSB2YXJfbmFtZSwKICAgICAgbmEudmFsdWUgPSAidHJhbnNwYXJlbnQiCiAgICApICsKICAgIGxhYnModGl0bGUgPSBjdXN0b21fdGl0bGVzW1t2YXJfbmFtZV1dKSArCiAgICB0aGVtZSgKICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLAogICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjMsICJjbSIpLAogICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LCBmYWNlID0gIml0YWxpYyIpLAogICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSwgZmFjZSA9ICJib2xkIiksCiAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiZ3JleSIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuOCkKICAgICkKfSkKCiMgQ29tYmluZSB0aGUgcGxvdHMgaW50byBhIGdyaWQgKDIgY29sdW1ucyBieSAyIHJvd3MpCmNvbWJpbmVkX3Bsb3QgPC0gKHBsb3RfbGlzdFtbMV1dICsgcGxvdF9saXN0W1syXV0pIC8KICAgICAgICAgICAgICAgICAocGxvdF9saXN0W1szXV0gKyBwbG90X2xpc3RbWzRdXSkKCmNvbWJpbmVkX3Bsb3QKYGBgCgpUaGVzZSBtYXBzIGFsc28gaGVscCBpZGVudGlmeSB3aGV0aGVyIHByZWRpY3RvcnMgYXJlIGNsb3NlbHkgcmVsYXRlZCB0byBlYWNoIG90aGVyLCB3aGljaCBjb3VsZCBjYXVzZSBtdWx0aWNvbGxpbmVhcml0eSBwcm9ibGVtcy4gVGhlICpQZXJjZW50IG9mIEJhY2hlbG9yJ3MgRGVncmVlIG9yIEhpZ2hlciogbWFwIGxvb2tzIHZlcnkgc2ltaWxhciB0byB0aGUgKkxvZyBUcmFuc2Zvcm1lZCBNZWRpYW4gSG91c2UgVmFsdWUqIG1hcCwgc3VnZ2VzdGluZyB0aGF0IGFyZWFzIHdpdGggbW9yZSBjb2xsZWdlIGdyYWR1YXRlcyB0ZW5kIHRvIGhhdmUgaGlnaGVyIGhvdXNlIHZhbHVlcy4gQWxzbywgdGhlICpQZXJjZW50IG9mIFZhY2FudCBIb3VzZXMqIGFuZCAqUGVyY2VudCBvZiBTaW5nbGUgSG91c2UgVW5pdHMqIG1hcHMgc2hhcmUgYSBzaW1pbGFyIHBhdHRlcm7igJROb3J0aCBQaGlsYWRlbHBoaWEgYW5kIFVuaXZlcnNpdHkgQ2l0eSBoYXZlIGEgaGlnaCBwZXJjZW50YWdlIG9mIHZhY2FudCBob3VzZXMgYW5kIGEgbG93IHBlcmNlbnRhZ2Ugb2Ygc2luZ2xlLWhvdXNlIHVuaXRzLCB3aGlsZSBHZXJtYW50b3duL0NoZXN0bnV0IEhpbGwgYW5kIEZhciBOb3J0aGVhc3QgUGhpbGFkZWxwaGlhIHNob3cgdGhlIG9wcG9zaXRlIHRyZW5kLiBUaGlzIHN1Z2dlc3RzIHRoYXQgdGhlc2UgdHdvIHByZWRpY3RvcnMgbWF5IGJlIHN0cm9uZ2x5IHJlbGF0ZWQsIHdoaWNoIGNvdWxkIGxlYWQgdG8gbXVsdGljb2xsaW5lYXJpdHkgaXNzdWVzIGluIHRoZSByZWdyZXNzaW9uIGFuYWx5c2lzLgoKIyMjIEV4YW1pbmluZyBNdWx0aWNvbGxpbmVhcml0eSAmIENvcnJlbGF0aW9uIE1hdHJpeAoKVG8gZnVydGhlciBleGFtaW5lIG11bHRpY29sbGluZWFyaXR5LCB3ZSBjcmVhdGUgYSBjb3JyZWxhdGlvbiBtYXRyaXggYmV0d2VlbiBwcmVkaWN0b3JzLiBBbGwgY29ycmVsYXRpb24gdmFsdWVzIGFyZSBiZWxvdyAwLjcsIGluZGljYXRpbmcgdGhhdCBubyBzZXZlcmUgbXVsdGljb2xsaW5lYXJpdHkgb2NjdXJzIGluIG91ciBtb2RlbC4gIAoKQW1vbmcgdGhlbSwgKiolIG9mIFNpbmdsZSBIb3VzZSBVbml0cyoqIGFuZCAqKkxvZ2dlZCBIb3VzZWhvbGRzIExpdmluZyBpbiBQb3ZlcnR5KiogaGF2ZSBhIGNvcnJlbGF0aW9uIG9mIC0wLjMyLCBzdWdnZXN0aW5nIHNvbWUgcmVsYXRpb25zaGlwIGJ1dCBub3Qgc3Ryb25nIGVub3VnaCB0byBjYXVzZSBzZXZlcmUgbXVsdGljb2xsaW5lYXJpdHkuIExvb2tpbmcgYmFjayBhdCB0aGUgY2hvcm9wbGV0aCBtYXBzIG9mIHRoZXNlIHR3byBwcmVkaWN0b3JzLCB0aGVpciBzcGF0aWFsIHBhdHRlcm5zIGFyZSBub3Qgc2ltaWxhci4gKiolIG9mIFNpbmdsZSBIb3VzZSBVbml0cyoqIGFuZCAqKiUgb2YgSW5kaXZpZHVhbHMgd2l0aCBhIEJhY2hlbG9yJ3MgRGVncmVlIG9yIEhpZ2hlcioqIGhhdmUgYSBjb3JyZWxhdGlvbiBvZiAtMC4zLCBhZ2FpbiBpbmRpY2F0aW5nIHNvbWUgcmVsYXRpb25zaGlwIHdpdGhvdXQgc2V2ZXJlIG11bHRpY29sbGluZWFyaXR5LiBUaGUgY2hvcm9wbGV0aCBtYXBzIG9mIHRoZXNlIHR3byBwcmVkaWN0b3JzIGFsc28gZG8gbm90IGV4aGliaXQgc2ltaWxhciBzcGF0aWFsIHBhdHRlcm5zLiBBZGRpdGlvbmFsbHksIHdoaWxlIHRoZSBjaG9yb3BsZXRoIG1hcHMgb2YgKipQZXJjZW50IG9mIFZhY2FudCBIb3VzZXMqKiBhbmQgKipQZXJjZW50IG9mIFNpbmdsZSBIb3VzZSBVbml0cyoqIHNoYXJlIGEgc2ltaWxhciBwYXR0ZXJuLCBhcyBtZW50aW9uZWQgYmVmb3JlLCB0aGVpciBjb3JyZWxhdGlvbiB2YWx1ZSBpcyBvbmx5IDAuMiwgc3VnZ2VzdGluZyBhIHdlYWsgcmVsYXRpb25zaGlwIHdpdGhvdXQgbXVsdGljb2xsaW5lYXJpdHkuICAKClRoZXJlIGlzIG5vIHNldmVyZSBtdWx0aWNvbGxpbmVhcml0eSBhbW9uZyB0aGUgcHJlZGljdG9ycywgc3VwcG9ydGluZyB0aGUgYXNzdW1wdGlvbnMgb2YgT0xTIHJlZ3Jlc3Npb24uIEhvd2V2ZXIsIGlmIHRoZSBjb3JyZWxhdGlvbiBtYXRyaXggaGFkIHNob3duIGhpZ2ggY29ycmVsYXRpb25zIChcXCh8cnwgXGdlcSAwLjdcXCkpLCB3ZSBjb3VsZCBmdXJ0aGVyIGNvbmZpcm0gdGhlIHNldmVyaXR5IG9mIG11bHRpY29sbGluZWFyaXR5IHVzaW5nIHRoZSAqKlZhcmlhbmNlIEluZmxhdGlvbiBGYWN0b3IgKFZJRikqKiAoKipWSUYgPCA1KiogaW5kaWNhdGVzIGxvdyBtdWx0aWNvbGxpbmVhcml0eSBhbmQgaXMgZ2VuZXJhbGx5IGFjY2VwdGFibGUsIHdoaWxlICoqVklGIFwoXGdlcVwpIDUqKiBzdWdnZXN0cyBtb2RlcmF0ZSB0byBoaWdoIG11bHRpY29sbGluZWFyaXR5IHRoYXQgbWF5IHJlcXVpcmUgYXR0ZW50aW9uLiBJZiAqKlZJRiBcKFxnZXFcKSAxMCoqLCBzZXZlcmUgbXVsdGljb2xsaW5lYXJpdHkgaXMgcHJlc2VudCwgbmVjZXNzaXRhdGluZyBjb3JyZWN0aXZlIG1lYXN1cmVzKS4gIAoKYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CgpjdXN0b21fbGFiZWxzIDwtIGMoCiAgIiUgb2YgSW5kaXZpZHVhbHMgd2l0aCBCYWNoZWxvcuKAmXMgRGVncmVlcyBvciBIaWdoZXIiID0gIlBDVEJBQ0hNT1IiLAogICIlIG9mIFZhY2FudCBIb3VzZXMiID0gIlBDVFZBQ0FOVCIsCiAgIiUgb2YgU2luZ2xlIEhvdXNlIFVuaXRzIiA9ICJQQ1RTSU5HTEVTIiwKICAiIyBIb3VzZWhvbGRzIExpdmluZyBpbiBQb3ZlcnR5IiA9ICJMTk5CRUxQT1YxMDAiCikKCnByZWRpY3Rvcl92YXJzIDwtIGRhdGFbLCBjKCJQQ1RWQUNBTlQiLCAiUENUU0lOR0xFUyIsICJQQ1RCQUNITU9SIiwgIkxOTkJFTFBPVjEwMCIpXQoKY29yX21hdHJpeCA8LSBjb3IocHJlZGljdG9yX3ZhcnMsIHVzZSA9ICJjb21wbGV0ZS5vYnMiLCBtZXRob2QgPSAicGVhcnNvbiIpCgpwcmludChjb3JfbWF0cml4KQpyb3duYW1lcyhjb3JfbWF0cml4KSA8LSBuYW1lcyhjdXN0b21fbGFiZWxzKQpjb2xuYW1lcyhjb3JfbWF0cml4KSA8LSBuYW1lcyhjdXN0b21fbGFiZWxzKQoKCmdnY29ycnBsb3QoY29yX21hdHJpeCwgCiAgICAgICAgICAgbWV0aG9kID0gInNxdWFyZSIsICAgCiAgICAgICAgICAgdHlwZSA9ICJsb3dlciIsICAgICAgCiAgICAgICAgICAgbGFiID0gVFJVRSwgICAgICAgCiAgICAgICAgICAgbGFiX3NpemUgPSAzLCAgICAgIAogICAgICAgICAgIGNvbG9ycyA9IGMoIiNkNzMwMjciLCAid2hpdGUiLCAiIzFhOTg1MCIpKSsKICAgIGxhYnModGl0bGUgPSAiQ29ycmVsYXRpb24gTWF0cml4IGZvciBhbGwgUHJlZGljdG9yIFZhcmlhYmxlcyIpICsKICAgIHRoZW1lKHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksIGZhY2UgPSAiaXRhbGljIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLCAKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gNyksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcpLCAKICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkKYGBgCgojIyBSZWdyZXNzaW9uIFJlc3VsdHMKCiMjIyBQYXJhbWV0ZXIgRXN0aW1hdGlvbnMKCkZvdXIgaW5kZXBlbmRlbnQgdmFyaWFibGVzIHdlcmUgaW5jbHVkZWQgaW4gdGhlIG11bHRpcGxlIHJlZ3Jlc3Npb24gbW9kZWwgdG8gcHJlZGljdCB0aGUgbG9nLXRyYW5zZm9ybWVkIG1lZGlhbiBob3VzZSB2YWx1ZSAoYExOTUVESFZBTGApIGluIFBoaWxhZGVscGhpYSBhdCBjZW5zdXMgYmxvY2sgZ3JvdXAgbGV2ZWwsIGluY2x1ZGluZyB0aGUgcHJvcG9ydGlvbiBvZiB2YWNhbnQgaG91c2luZyB1bml0cyAoYFBDVFZBQ0FOVGApLCB0aGUgcHJvcG9ydGlvbiBvZiBzaW5nbGUtZmFtaWx5IGhvdXNpbmcgdW5pdHMgKGBQQ1RTSU5HTEVTYCksIHRoZSBwcm9wb3J0aW9uIG9mIHJlc2lkZW50cyB3aXRoIGEgYmFjaGVsb3IncyBkZWdyZWUgb3IgaGlnaGVyIChgUENUQkFDSE1PUmApLCBhbmQgdGhlIG51bWJlciBvZiBob3VzZWhvbGRzIGxpdmluZyBiZWxvdyB0aGUgcG92ZXJ0eSBsaW5lIChgTE5OQkVMUE9WMTAwYCkuIFRoZSByZWdyZXNzaW9uIHJlc3VsdHMgYXJlIHByZXNlbnRlZCBiZWxvdzoKCmBgYHtyIHJlZ3Jlc3Npb259CmZpdCA8LSBsbShMTk1FREhWQUwgfiBQQ1RWQUNBTlQgKyBQQ1RTSU5HTEVTICsgUENUQkFDSE1PUiArIExOTkJFTFBPVjEwMCwgZGF0YT1kYXRhKQpzdW1tYXJ5KGZpdCkKYGBgClRoZSByZWdyZXNzaW9uIG91dHB1dCB0ZWxscyB1cyB0aGF0IHRoZSBtZWRpYW4gaG91c2luZyB2YWx1ZXMgYXJlIGhpZ2hseSBzaWduaWZpY2FudCBjb3JyZWxhdGVkIHdpdGggdGhlIHByb3BvcnRpb24gb2YgdmFjYW50IGhvdXNpbmcgdW5pdHMoYFBDVFZBTlRgKSwgdGhlIHByb3BvcnRpb24gb2Ygc2luZ2xlLWZhbWlseSBob3VzaW5nIHVuaXRzKGBQQ1RTSU5HTEVTYCksIHRoZSBwcm9wb3J0aW9uIG9mIHJlc2lkZW50cyB3aXRoIGEgYmFjaGVsb3IncyBkZWdyZWUgb3IgaGlnaGVyIChgUENUQkFDSE1PUmApLCBhbmQgdGhlIGxvZy10cmFuc2Zvcm1lZCBudW1iZXIgb2YgaG91c2Vob2xkcyBsaXZpbmcgYmVsb3cgdGhlIHBvdmVydHkgbGluZSAoYExOTkJFTFBPVmApLCB3aXRoICRwLXZhbHVlPDAuMDAwMSQgZm9yIGFsbCBmb3VyIHByZWRpY3RvcnMuIAoKQXMgdGhlIHByb3BvcnRpb25zIG9mIHZhY2FudCBob3VzaW5nIHVuaXRzIChgUENUVkFOVGApIGdvZXMgdXAgYnkgMSB1bml0ICgxJSksIHRoZSBtZWRpYW4gaG91c2UgdmFsdWUgZ29lcyBkb3duIGJ5IGFwcHJveGltYXRlbHkgMS45MTUlLCB3aXRoIGhvbGRpbmcgYWxsIG90aGVyIHRocmVlIHByZWRpY3RvcnMgY29uc3RhbnQuIEluIGFkZGl0aW9uLCB0aGUgcmVzcGVjdGl2ZSAkcC12YWx1ZSQgZm9yICRcYmV0YV8xJCBpcyBsZXNzIHRoYW4gMC4wMDAxLCBpbmRpY2F0aW5nIHRoYXQgaWYgdGhlcmUgaXMgbm8gcmVsYXRpb25zaGlwIGJldHdlZW4gYFBDVFZBTlRgIGFuZCB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIChpLmUuLCBpZiB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgXCggXGJldGFfMSA9IDAgXCkgaXMgIHRydWUpLCB0aGVuIHRoZSBwcm9iYWJpbGl0eSBvZiBnZXR0aW5nIGEgXCggXGJldGFfMSBcKSBjb2VmZmljaWVudCBlc3RpbWF0ZSBvZiAtMC4wMTkxNTY5IGlzIGxlc3MgdGhhbiAwLjAwMDEuIFdlIGNhbiBzYWZlbHkgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgJEhfMDogXGJldGFfMSA9IDAkIGZvciAkSF9hOiBcYmV0YV8xIFxuZXEgMCQuIAoKJCQoZV57XGJldGF9IC0gMSkgXHRpbWVzIDEwMFwlID0gKGVeey0wLjAxOTE1Njl9IC0gMSkgXHRpbWVzIDEwMFwlIFxhcHByb3ggLTEuOTE1XCUgJCQKCgpTaW1pbGFybHksIGFzIHRoZSBwcm9wb3J0aW9uIG9mIHNpbmdsZS1mYW1pbHkgaG91c2luZyB1bml0cyAoYFBDVFNJTkdMRVNgKSBnb2VzIHVwIGJ5IDEgdW5pdCAoMSUpLCB0aGUgbWVkaWFuIGhvdXNlIHZhbHVlIGdvZXMgdXAgYnkgYXBwcm94aW1hdGVseSAwLjI5OCUsIHdpdGggaG9sZGluZyBhbGwgb3RoZXIgdGhyZWUgcHJlZGljdG9ycyBjb25zdGFudC4gVGhlICRwLXZhbHVlJCBmb3IgJFxiZXRhXzIkIGlzIGxlc3MgdGhhbiAwLjAwMDEsIGluZGljYXRpbmcgdGhhdCBpZiB0aGVyZSBpcyBubyByZWxhdGlvbnNoaXAgYmV0d2VlbiBgUENUU0lOR0xFU2AgYW5kIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgKGkuZS4sIGlmIHRoZSBudWxsIGh5cG90aGVzaXMgdGhhdCBcKCBcYmV0YV8yID0gMCBcKSBpcyAgdHJ1ZSksIHRoZW4gdGhlIHByb2JhYmlsaXR5IG9mIGdldHRpbmcgYSBcKCBcYmV0YV8yIFwpIGNvZWZmaWNpZW50IGVzdGltYXRlIG9mIDAuMDAyOTc2OSBpcyBsZXNzIHRoYW4gMC4wMDAxLiBXZSBjYW4gYWxzbyBzYWZlbHkgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgJEhfMDogXGJldGFfMiA9IDAkIGZvciAkSF9hOiBcYmV0YV8yIFxuZXEgMCQuCgokJChlXntcYmV0YX0gLSAxKSBcdGltZXMgMTAwXCUgPSAoZV57LTAuMDAyOTc2OX0gLSAxKSBcdGltZXMgMTAwXCUgXGFwcHJveCAwLjI5OFwlICQkCgpGdXJ0aGVybW9yZSwgYXMgdGhlIHByb3BvcnRpb24gb2YgcmVzaWRlbnRzIHdpdGggYSBiYWNoZWxvcidzIGRlZ3JlZSBvciBoaWdoZXIgKGBQQ1RCQUNITU9SYCkgZ29lcyB1cCBieSAxIHVuaXQgKDElKSwgdGhlIG1lZGlhbiBob3VzZSB2YWx1ZSBnb2VzIHVwIGJ5IGFwcHJveGltYXRlbHkgMi4wOSUsIHdpdGggaG9sZGluZyBhbGwgb3RoZXIgdGhyZWUgcHJlZGljdG9ycyBjb25zdGFudC4gU2ltaWxhciB0byAkXGJldGFfMiQsIHRoZSAkcC12YWx1ZSQgZm9yICRcYmV0YV8zJCBpcyBsZXNzIHRoYW4gMC4wMDAxLCBpbmRpY2F0aW5nIHRoYXQgaWYgdGhlcmUgaXMgbm8gcmVsYXRpb25zaGlwIGJldHdlZW4gYFBDVEJBQ0hNT1JgIGFuZCB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIChpLmUuLCBpZiB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgXCggXGJldGFfMyA9IDAgXCkgaXMgIHRydWUsIHRoZW4gdGhlIHByb2JhYmlsaXR5IG9mIGdldHRpbmcgYSBcKCBcYmV0YV8zIFwpIGNvZWZmaWNpZW50IGVzdGltYXRlIG9mIDAuMDIwOTA5OCBpcyBsZXNzIHRoYW4gMC4wMDAxLiBXZSBjYW4gYWxzbyBzYWZlbHkgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgJEhfMDogXGJldGFfMyA9IDAkIGZvciAkSF9hOiBcYmV0YV8zIFxuZXEgMCQuCgokJChlXntcYmV0YX0gLSAxKSBcdGltZXMgMTAwXCUgPSAoZV57MC4wMjA5MDk4fSAtIDEpIFx0aW1lcyAxMDBcJSBcYXBwcm94IDIuMDlcJSAkJAoKTGFzdGx5LCBhcyAxIHBlcmNlbnQgaW5jcmVhc2UgaW4gdGhlIG51bWJlciBvZiBob3VzZWhvbGRzIGxpdmluZyBiZWxvdyB0aGUgcG92ZXJ0eSBsaW5lLCB0aGUgbWVkaWFuIGhvdXNlIHZhbHVlIGdvZXMgZG93biBieSBhcHByb3hpbWF0ZWx5IDAuMDc4JSAsIHdpdGggaG9sZGluZyBhbGwgb3RoZXIgdGhyZWUgcHJlZGljdG9ycyBjb25zdGFudC4gVGhlICRwLXZhbHVlJCBmb3IgJFxiZXRhXzQkIGlzIGFsc28gbGVzcyB0aGFuIDAuMDAwMSAgaW5kaWNhdGluZyB0aGF0IGlmIHRoZXJlIGlzIG5vIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIG51bWJlciBvZiBob3VzZWhvbGRzIGJlbG93IHBvdmVydHkgbGluZSBhbmQgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSAoaS5lLiwgaWYgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IFwoIFxiZXRhXzQgPSAwIFwpIGlzICB0cnVlKSwgdGhlbiB0aGUgcHJvYmFiaWxpdHkgb2YgZ2V0dGluZyBhIFwoIFxiZXRhXzQgXCkgY29lZmZpY2llbnQgZXN0aW1hdGUgb2YgLTAuMDc4OTA1NCBpcyBsZXNzIHRoYW4gMC4wMDAxLiBBcyBzdGF0ZWQgYmVmb3JlLCB3ZSBjYW4gYWxzbyBzYWZlbHkgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgJEhfMDogXGJldGFfNCA9IDAkIGZvciAkSF9hOiBcYmV0YV80IFxuZXEgMCQuCgokJCgxLjAxXntcYmV0YX0gLSAxKSBcdGltZXMgMTAwXCUgPSAoMS4wMV57LTAuMDc4OTA1NH0gLSAxKSBcdGltZXMgMTAwXCUgIFxhcHByb3ggLTAuMDc4XCUkJAoKIyMjIE1vZGVsIEZpdAoKYGBge3IgcmVncmVzc2lvbjF9CmZpdCA8LSBsbShMTk1FREhWQUwgfiBQQ1RWQUNBTlQgKyBQQ1RTSU5HTEVTICsgUENUQkFDSE1PUiArIExOTkJFTFBPVjEwMCwgZGF0YT1kYXRhKQpzdW1tYXJ5KGZpdCkKYGBgCkZpcnN0LCB0aGUgcmVzaWR1YWxzIGZyb20gdGhlIG1vZGVsIHNob3cgYSByZWFzb25hYmxlIGRpc3RyaWJ1dGlvbiBvZiBlcnJvcnMsIHdpdGggYSBtZWRpYW4gcmVzaWR1YWwgb2YgMC4wMzgyMiwgYSBtaW5pbXVtIHZhbHVlIG9mIC0yLjI2LCBhIGZpcnN0IHF1YXJ0aWxlIG9mIC0wLjIwLCBhbmQgYSB0aGlyZCBxdWFydGlsZSBvZiAwLjIyLCBhbmQgYSBtYXhpbXVtIHZhbHVlIG9mIDIuMjQuIFRoaXMgZGlzdHJpYnV0aW9uIHNob3dzIHRoYXQgdGhlIG1vZGVsIGNhcHR1cmVzIHRoZSB2YXJpYWJpbGl0eSBpbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIHdlbGwgKGxvZ2dlZCB0cmFuc2Zvcm1lZCBtZWRpYW4gaG9tZSB2YWx1ZSksIGFsdGhvdWdoIHNvbWUgb2YgdGhlIHJlc2lkdWFscyBhcmUgbGFyZ2VyIHRoYW4gMi41IHN0YW5kYXJkIGRldmlhdGlvbnMgZnJvbSB0aGUgbWVhbiwgd2hpY2ggYXJlIHRoZSBvdXRsaWVycy4KCk1vcmVvdmVyLCB0aGUgbW9kZWwgaGFzIGEgbXVsdGlwbGUgXChSXjJcKSB2YWx1ZSBvZiAwLjY2MjMgYW5kIGFuIGFkanVzdGVkIFwoUl4yXCkgdmFsdWUgb2YgMC42NjE1LCBpbmRpY2F0aW5nIHRoYXQgYXBwcm94aW1hdGVseSA2NiUgb2YgdGhlIHZhcmlhbmNlIGluIGBMTk1FREhWQUxgIGlzIGV4cGxhaW5lZCBieSB0aGUgcHJlZGljdG9ycy4gIFRoZSAkRi1zdGF0aXN0aWMkIG9mIDg0MC4wIHdpdGggYSAkcC12YWx1ZSQgbGVzcyB0aGFuIDAuMDAwMSwgaW5kaWNhdGluZyB0aGF0IHRoZSBtb2RlbCBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LgoKYGBge3J9CmFub3ZhX3RhYmxlIDwtIGFub3ZhKGZpdCkKYW5vdmFfdGFibGUKYGBgCgpUaGUgQW5hbHlzaXMgb2YgVmFyaWFuY2UgKEFOT1ZBKSB0YWJsZSBzaG93cyBhZGRpdGlvbmFsIGluc2lnaHQgaW50byB0aGUgc2lnbmlmaWNhbmNlIG9mIGVhY2ggcHJlZGljdG9yIGluIGV4cGxhaW5pbmcgdGhlIHZhcmlhdGlvbiBpbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIChgTE5WTUVESFZBTGApLiBGb3IgcHJvcG9ydGlvbiBvZiB2YWNhbnQgaG91c2luZyB1bml0cyAoYFBDVFZBQ0FOVGApLCB0aGUgc3VtIG9mIHNxdWFyZXMgaXMgMTgwLjM5MiwgaW5kaWNhdGluZyB0aGF0IHRob3NlIGFtb3VudCBvZiB2YXJpYXRpb24gaW4gYExOVk1FREhWQUxgIHRoYXQgY2FuIGJlIGF0dHJpYnV0ZWQgdG8gY2hhbmdlcyBpbiBgUENUVkFDQU5UYC4gQSBoaWdoZXIgc3VtIG9mIHNxdWFyZXMgaW5kaWNhdGVzIGEgbWhpZ2hlciByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgcHJlZGljdG9yIGFuZCB0aGUgZGVwZW5kZW50IHZhcmlhYmxlLiBUaGUgc3VtIG9mIHNxdWFyZXMgZm9yIHRoZSBwZXJjZW50YWdlIG9mIHJlc2lkZW50cyB3aXRoIGEgYmFjaGVsb3IncyBkZWdyZWUgb3IgaGlnaGVyIChgUENUQkFDSE1PUmApIGV4cGxhaW5zIHRoZSBoaWdoZXN0IHBvcnRpb24gb2YgdGhlIHZhcmlhbmNlIGluIGBMTlZNRURIVkFMYC4gSW4gY29udHJhc3QsIHRoZSBzdW0gb2Ygc3F1YXJlcyBmb3IgdGhlIGxvZy10cmFuc2Zvcm1lZCBudW1iZXIgb2YgaG91c2Vob2xkcyBsaXZpbmcgYmVsb3cgdGhlIHBvdmVydHkgbGluZSAoYExOTkJFTFBPVjEwMGApIGV4cGxhaW5zIHRoZSBsZWFzdCBhbW91bnQgb2YgdmFyaWFuY2UgaW4gYExOVk1FREhWQUxgLCB3aXRoIG9ubHkgMTEuNjkuIAoKVGhlIHRvdGFsIHN1bSBvZiBzcXVhcmVzLCB3aGljaCByZXByZXNlbnRzIHRoZSB0b3RhbCB2YXJpYW5jZSBpbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIChgTE5WTUVESFZBTGApLCBpcyAyMzAuMzQsIHdpdGggYSBtZWFuIHNxdWFyZSBlcnJvciBvZiAwLjEzNC4gT3ZlcmFsbCwgdGhlIEFOT1ZBIHRhYmxlIHByb3ZpZGVzIGEgY29tcHJlaGVuc2l2ZSBvdmVydmlldyBvZiB0aGUgc2lnbmlmaWNhbmNlIG9mIGVhY2ggcHJlZGljdG9yIGluIHRoZSBtb2RlbCBhbmQgdGhlIHByb3BvcnRpb24gb2YgdmFyaWFuY2UgZXhwbGFpbmVkIGJ5IGVhY2ggcHJlZGljdG9yLiBJdCBjb25maXJtcyB0aGF0IGFsbCBmb3VyIHByZWRpY3RvcnMgY29udHJpYnV0ZSBzaWduaWZpY2FudGx5IHRvIGV4cGxhaW5pbmcgdGhlIHZhcmlhbmNlIGluIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUuIFRoZXNlIGZpbmRpbmdzIHByb3ZpZGUgc3Ryb25nIGV2aWRlbmNlIG9mIHRoZSByb2J1c3RuZXNzIG9mIHRoZSBtb2RlbCBhbmQgdGhlIHJlbGV2YW5jZSBvZiBuZWlnaGJvdXJob29kIGNoYXJhY3RlcmlzdGljcyBpbiBwcmVkaWN0aW5nIGhvdXNpbmcgdmFsdWVzLgoKCiMjIFJlZ3Jlc3Npb24gQXNzdW1wdGlvbnMgQ2hlY2sKCkluIHRoaXMgc2VjdGlvbiwgd2UgY29uZHVjdGVkIHZhcmlldHkgb2YgYW5hbHlzaXMgdG8gY2hlY2sgaWYgdGhlIGFzc3VtcHRpb24gb2YgdGhlIGxpbmVhciByZWdyZXNzaW9uIHdlcmUgbWV0LiBJbiB0aGUgZWFybGllciBzZWN0aW9uLCB3ZSBhbHJlYWR5IGNoZWNrZWQgdGhlIHZhcmlhYmxlIGRpc3RyaWJ1dGlvbiBhbmQgbXVsdGljb2xsaW5lYXJpdHkuIEhlcmUsIHdlIHdpbGwgY2hlY2sgZm9sbG93aW5nIGFzc3VtcHRpb246CgotIExpbmVhcml0eQotIE5vcm1hbGl0eSBvZiBSZXNpZHVhbHMKLSBIb21vc2NlZGFzdGljaXR5CgojIyMgTGluZWFyaXR5CgpUbyBmdXJ0aGVyIGV4YW1pbmUgdGhlIGxpbmVhciByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIGFuZCB0aGUgcHJlZGljdG9ycywgd2UgY3JlYXRlIGZvdXIgc2NhdHRlciBwbG90cywgd2hlcmUgdGhlIHgtYXhpcyByZXByZXNlbnRzIGVhY2ggcHJlZGljdG9yIGFuZCB0aGUgeS1heGlzIHJlcHJlc2VudHMgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSwgKkxvZyBUcmFuc2Zvcm1lZCBNZWRpYW4gSG91c2UgVmFsdWUqLiAKCmBgYHtyIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTksIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmxvbmdlcjwtZGF0YSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGMoIlBDVEJBQ0hNT1IiLCAiTE5OQkVMUE9WMTAwIiwgIlBDVFZBQ0FOVCIsICJQQ1RTSU5HTEVTIiksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIlZhcmlhYmxlIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIlZhbHVlIikKCmdncGxvdChsb25nZXIsYWVzKHggPSBWYWx1ZSwgeSA9IExOTUVESFZBTCkpICsKICBnZW9tX3BvaW50KGNvbG9yID0gImJsYWNrIiwgc2l6ZT0gMC40KSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sb3IgPSAicmVkIiwgc2UgPSBGQUxTRSkgKyAKICBmYWNldF93cmFwKH4gVmFyaWFibGUsIHNjYWxlcyA9ICJmcmVlIiwgbGFiZWxsZXIgPSBhc19sYWJlbGxlcihjKAogICAgIlBDVEJBQ0hNT1IiID0gIiUgd2l0aCBCYWNoZWxvcuKAmXMgRGVncmVlcyBvciBIaWdoZXIiLAogICAgIkxOTkJFTFBPVjEwMCIgPSAiTG9nZ2VkIEhvdXNlaG9sZHMgTGl2aW5nIGluIFBvdmVydHkiLAogICAgIlBDVFZBQ0FOVCIgPSAiJSBvZiBWYWNhbnQgSG91c2VzIiwKICAgICJQQ1RTSU5HTEVTIiA9ICIlIG9mIFNpbmdsZSBIb3VzZSBVbml0cyIKICApKSkgICsKICB0aGVtZV9saWdodCgpICsgICAKICB0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LGZhY2UgPSAiaXRhbGljIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLCAKICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT02KSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT02KSwgCiAgICAgICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT04KSkgKwogIGxhYnModGl0bGUgPSAiU2NhdHRlciBQbG90cyBvZiBEZXBlbmRlbnQgVmFyaWFibGUgdnMuIFByZWRpY3RvcnMiLCAKICAgICAgIHggPSAiUHJlZGljdG9yIFZhbHVlIiwgCiAgICAgICB5ID0gIkxvZyBvZiBNZWRpYW4gSG91c2UgVmFsdWUiKQpgYGAKCkZyb20gdGhlIHBsb3RzLCB3ZSBvYnNlcnZlIHRoZSBmb2xsb3dpbmcgdHJlbmRzOiAgCgotICoqTG9nZ2VkIEhvdXNlaG9sZHMgTGl2aW5nIGluIFBvdmVydHkqKiBzaG93cyBhIG5lZ2F0aXZlIGxpbmVhciByZWxhdGlvbnNoaXAgd2l0aCB0aGUgZGVwZW5kZW50IHZhcmlhYmxlLiBBcyB0aGUgcGVyY2VudGFnZSBvZiBob3VzZWhvbGRzIGxpdmluZyBpbiBwb3ZlcnR5IGluY3JlYXNlcywgdGhlICpMb2cgVHJhbnNmb3JtZWQgTWVkaWFuIEhvdXNlIFZhbHVlKiBkZWNyZWFzZXMuIFRoaXMgaXMgcmVmbGVjdGVkIGluIGl0cyBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBcXCg8IDBcXCkuIEhvd2V2ZXIsIHRoZSBhc3NvY2lhdGlvbiBpcyBub3Qgc3RyaWN0bHkgbGluZWFyLiBJbiB0aGUgZ3JhcGgsIHRoZSBwb2ludHMgYXJlIG1vcmUgc2NhdHRlcmVkIHdpZGVseSwgcGFydGljdWxhciBhdCBsb3dlciBsZXZlbCBvZiBwb3ZlcnR5LCB3aGVyZSBob3VzaW5nIHZhbHVlcyB2YXJ5IHNpZ25pZmljYW50bHkuIFRoaXMgaW5kaWNhdGUgd2hpbGUgcG92ZXJ0eSBsZXZlbHMgaGF2ZSBhIG5lZ2F0aXZlIGltcGFjdCBvbiBob3VzaW5nIHZhbHVlcywgdGhlIGVmZmVjdCBpcyBub3QgdW5pZm9ybSBhY3Jvc3MgYWxsIGJsb2NrIGdyb3Vwcy4gVGhlcmUgaXMgYSBzdWJzdGFudGlhbCB2YXJpYXRpb24gaW4gaG91c2luZyB2YWx1ZXMgZXZlbiBhdCBzaW1pbGFyIHBvdmVydHkgbGV2ZWxzLCB3aGljaCBzdWdnZXN0cyB0aGF0IG90aGVyIGZhY3RvcnMgbWF5IGFsc28gYmUgaW5mbHVlbmNpbmcgaG91c2luZyB2YWx1ZXMuCgotICoqJSB3aXRoIEJhY2hlbG9y4oCZcyBEZWdyZWVzIG9yIEhpZ2hlcioqIGV4aGliaXRzIGEgcG9zaXRpdmUgbGluZWFyIHJlbGF0aW9uc2hpcCB3aXRoIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUuIFdoZW4gdGhlIHBlcmNlbnRhZ2Ugb2YgaW5kaXZpZHVhbHMgd2l0aCBhIGJhY2hlbG9yJ3MgZGVncmVlIG9yIGhpZ2hlciBpbmNyZWFzZXMsIHRoZSAqTG9nIFRyYW5zZm9ybWVkIE1lZGlhbiBIb3VzZSBWYWx1ZSogYWxzbyByaXNlcywgd2l0aCBhIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IFxcKD4gMFxcKS4gIFRoZSBwb2ludHMgb24gdGhlIGdyYXBoIGZvcm0gYSB0aWdodCBiYW5kIGFsb25nIHRoZSB0cmVuZCBsaW5lLCBpbmRpY2F0aW5nIHRoYXQgaGlnaGVyIGVkdWNhdGlvbiBsZXZlbHMgd2l0aGluIGEgbmVpZ2hib3Job29kIGlzIGhpZ2hseSBjb3JyZWxhdGVkIHdpdGggaGlnaGVyIGhvdXNpbmcgdmFsdWVzLiBUaGUgY29uc2lzdGVudCB1cHdhcmQgdHJlbmQgc3VnZ2VzdCB0aGF0IGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQgaXMgYSBrZXkgZHJpdmVyIG9mIGhvdXNpbmcgcHJpY2VzLCBhbmQgYSBjbGVhciBsaW5lYXIgdHJlbmQgaW1wbGllcyB0aGF0IHRoaXMgdmFyaWFibGUgaXMgc3VpdGFibGUgZm9yIHRoaXMgbGluZWFyIHJlZ3Jlc3Npb24gYW5hbHlzaXMuCgotICoqJSBvZiBTaW5nbGUgSG91c2UgVW5pdHMqKiBoYXMgYSB3ZWFrZXIgYnV0IHN0aWxsIHBvc2l0aXZlIHJlbGF0aW9uc2hpcCB3aXRoIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUuIFdoaWxlIHRoZSB0cmVuZCBpcyBub3Qgb2J2aW91cywgYXJlYXMgd2l0aCBhIGhpZ2hlciBwZXJjZW50YWdlIG9mIHNpbmdsZS1ob3VzZSB1bml0cyB0ZW5kIHRvIGhhdmUgaGlnaGVyICpMb2cgVHJhbnNmb3JtZWQgTWVkaWFuIEhvdXNlIFZhbHVlcyosIGVzcGVjaWFsbHkgd2hlbiB0aGUgcGVyY2VudGFnZSBpcyBzdWZmaWNpZW50bHkgbGFyZ2UuIFRoZSBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBpcyBcXCg+IDBcXCkuIFRoZSBzY2F0dGVyIHBvaW50cyBzaG93cyBzaWduaWZpY2FudCB2YXJpYWJpbGl0eSBpbiBob3VzaW5nIHZhbHVlcyBhdCB2YXJpb3VzIGxldmVscyBvZiBzaW5nbGUtaG91c2UgdW5pdHMsIHdpdGggc29tZSBibG9jayBncm91cHMgaGF2aW5nIGhpZ2ggaG91c2luZyB2YWx1ZXMgZGVzcGl0ZSBhIGxvdyBwZXJjZW50YWdlIG9mIHNpbmdsZS1ob3VzZSB1bml0cy4gVGhpcyB2YXJpYWJpbGl0eSBzdWdnZXN0cyB0aGF0IHdoaWxlIHRoZXJlIGlzIGEgcG9zaXRpdmUgcmVsYXRpb25zaGlwIGJldHdlZW4gc2luZ2xlLWhvdXNlIHVuaXRzIGFuZCBob3VzaW5nIHZhbHVlcywgb3RoZXIgZmFjdG9ycyBtYXkgYWxzbyBiZSBpbmZsdWVuY2luZyBob3VzaW5nIHZhbHVlcyBhdCB0aGUgc2FtZSB0aW1lLiAKCi0gKiolIG9mIFZhY2FudCBIb3VzZXMqKiBoYXMgYSBnZW5lcmFsIG5lZ2F0aXZlIGxpbmVhciByZWxhdGlvbnNoaXAgd2l0aCB0aGUgZGVwZW5kZW50IHZhcmlhYmxlLiBBcyB0aGUgcGVyY2VudGFnZSBvZiB2YWNhbnQgaG91c2VzIGluY3JlYXNlcywgdGhlICpMb2cgVHJhbnNmb3JtZWQgTWVkaWFuIEhvdXNlIFZhbHVlKiBkZWNyZWFzZXMsIHdpdGggYSBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBcXCg8IDBcXCkuIEhvd2V2ZXIsIGluIHRoZSBncmFwaCwgaXQgcmV2ZWFscyBhIG1vcmUgY29tcGxleCByZWxhdGlvbnNoaXAgd2l0aCBzaWduaWZpY2FudCB2YXJpYXRpb24gaW4gaG91c2luZyB2YWx1ZXMgYWNyb3NzIGRpZmZlcmVudCB2YWNhbmN5IHJhdGVzLiBUaGVyZSBhcmUgY2x1c3RlcnMgb2YgYmxvY2sgZ3JvdXBzIHdpdGggaGlnaCBob3VzaW5nIHZhbHVlcyBhbmQgbG93IHZhY2FuY3kgcmF0ZXMsIGluZGljYXRpbmcgdGhhdCB0aGUgcmVsYXRpb25zaGlwIGlzIG5vdCBzdHJpY3RseSBsaW5lYXIuSW4gdGhlIG1pZGRsZSBhbmQgbG93ZXIgcmFuZ2VzIG9mIHZhY2FuY3kgcmF0ZXMsIHRoZSBkZWNsaW5lIGluIGhvdXNpbmcgdmFsdWVzIGJlY29tZXMgbGVzcyBwcm9ub3VuY2VkLiBUaGlzIHN1Z2dlc3RzIHRoYXQgd2hpbGUgdmFjYW50IGhvdXNpbmcgaXMgYXNzb2NpYXRlZCB3aXRoIGxvd2VyIHByb3BlcnR5IHZhbHVlcywgdGhlIGltcGFjdCBkaW1pbmlzaGVzIG9yIGJlY29tZXMgbGVzcyBwcmVkaWN0YWJsZSBhcyB0aGUgdmFjYW5jeSByYXRlIGNoYW5nZXMuICAKCkluIHN1bW1hcnksIHRoZSBzY2F0dGVycGxvdCBzaG93cyB0aGF0IHdoaWxlIHRoZSBQQ1RCQUNITU9SIGFuZCBMTk1FREhWQUwgaGF2ZSBhIGNsZWFyIGxpbmVhciByZWxhdGlvbnNoaXAsIHRoZSBvdGhlciBwcmVkaWN0b3JzIGhhdmUgbW9yZSBjb21wbGV4IG5vbi1saW5lYXIgcmVsYXRpb25zaGlwcyB3aXRoIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUuIFRoaXMgc3VnZ2VzdHMgdGhhdCB0aGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgbWF5IG5vdCBmdWxseSBjYXB0dXJlIHRoZSBjb21wbGV4aXR5IG9mIHRoZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gdGhlIHByZWRpY3RvcnMgYW5kIG1lZGlhbiBob3VzZSB2YWx1ZXMuCgoKIyMjIE5vcm1hbGl0eSBvZiBSZXNpZHVhbHMKCk5leHQsIHdlIGV4YW1pbmUgdGhlIG5vcm1hbGl0eSBvZiByZXNpZHVhbHMgb2YgdGhlIHJlZ3Jlc3Npb24gbW9kZWwuIFRoZSBoaXN0b2dyYW0gb2Ygc3RhbmRhcmRpemVkIHJlc2lkdWFscyBwcm92aWRlcyBhIGRldGFpbCB2aWV3IG9mIHRoZSAgb2YgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgcmVzaWR1YWxzIGZyb20gdGhlIE9MUyBtb2RlbCwgc2hvd2luZyBiZWxvdzoKCmBgYHtyLCBpbmNsdWRlPSBGQUxTRX0KZml0dGVkX3ZhbHVlcyA8LSBmaXR0ZWQoZml0KQpyZXNpZHVhbHNfdmFsdWVzIDwtIHJlc2lkdWFscyhmaXQpCnN0YW5kYXJkaXplZF9yZXNpZHVhbHMgPC0gcnN0YW5kYXJkKGZpdCkKCmRhdGEgPC0gZGF0YSAlPiUKICBtdXRhdGUoCiAgICBGaXR0ZWQgPSBmaXR0ZWRfdmFsdWVzLAogICAgUmVzaWR1YWxzID0gcmVzaWR1YWxzX3ZhbHVlcywKICAgIFN0YW5kYXJkaXplZF9SZXNpZHVhbHMgPSBzdGFuZGFyZGl6ZWRfcmVzaWR1YWxzKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoZGF0YSwgYWVzKHggPSBTdGFuZGFyZGl6ZWRfUmVzaWR1YWxzKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbnMgPSAzMCwgZmlsbCA9ICJibGFjayIpICsKICBsYWJzKHRpdGxlID0gIkhpc3RvZ3JhbSBvZiBTdGFuZGFyZGl6ZWQgUmVzaWR1YWxzIiwgCiAgICAgICB4ID0gIlN0YW5kYXJkaXplZCBSZXNpZHVhbHMiLCAKICAgICAgIHkgPSAiRnJlcXVlbmN5IikgKwogIHRoZW1lX21pbmltYWwoKSArICAgCiAgdGhlbWUocGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSxmYWNlID0gIml0YWxpYyIpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwgCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KHNpemU9NiksCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KHNpemU9NiksIAogICAgICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9OCkpCmBgYAoKYGBge3J9CmdncGxvdChkYXRhLCBhZXMoeCA9IEZpdHRlZCwgeSA9IFN0YW5kYXJkaXplZF9SZXNpZHVhbHMpKSArCiAgZ2VvbV9wb2ludChjb2xvciA9ICJibGFjayIsIHNpemU9IDAuNCkgKyAgICAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJyZWQiKSArICAKICBsYWJzKAogICAgdGl0bGUgPSAiU2NhdHRlciBQbG90IG9mIFN0YW5kYXJkaXplZCBSZXNpZHVhbHMgdnMgRml0dGVkIFZhbHVlcyIsCiAgICB4ID0gIlByZWRpY3RlZCBWYWx1ZXMiLAogICAgeSA9ICJTdGFuZGFyZGl6ZWQgUmVzaWR1YWxzIgogICkgKwogIHRoZW1lX21pbmltYWwoKSArICAgCiAgdGhlbWUocGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSxmYWNlID0gIml0YWxpYyIpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwgCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KHNpemU9NiksCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KHNpemU9NiksIAogICAgICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9OCkpCmBgYAoKCmBgYHtyLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD05LCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpqb2luPC0gZGF0YSAlPiUKICBkcGx5cjo6c2VsZWN0KFBPTFlfSUQsIFN0YW5kYXJkaXplZF9SZXNpZHVhbHMpCgpzaGFwZSA8LSBzaGFwZSAlPiUKICBsZWZ0X2pvaW4oam9pbiwgYnkgPSBjKCJQT0xZX0lEIiA9ICJQT0xZX0lEIikpCgpnZ3Bsb3Qoc2hhcGUpKwogIGdlb21fc2YoYWVzKGZpbGwgPSBTdGFuZGFyZGl6ZWRfUmVzaWR1YWxzKSwgY29sb3IgPSAidHJhbnNwYXJlbnQiKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3JzID0gYygiI2ZmZjBmMyIsICIjYTQxMzNjIiksIAogICAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAiU3RkIFJlc2lkdWFscyIsIAogICAgICAgICAgICAgICAgICAgICAgIG5hLnZhbHVlID0gInRyYW5zcGFyZW50IikgKyAgIyBDaG9vc2UgYSBjb2xvciBwYWxldHRlLCBpbnZlcnQgZGlyZWN0aW9uIGlmIG5lZWRlZAogIGxhYnModGl0bGUgPSAiQ2hvcm9wbGV0aCBNYXAgb2YgU3RhbmRhcmRpemVkIFJlc2lkdWFscyIpICsKICB0aGVtZShsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOSksCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LCBmYWNlID0gIml0YWxpYyIpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiZ3JleSIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuOCkpCgpgYGAKCgoKCiMjIEFkZGl0aW9uYWwgQW5hbHlzaXMKCmBgYHtyfQpzdGVwd2lzZV9tb2RlbCA8LSAgc3RlcEFJQyhmaXQsIGRpcmVjdGlvbiA9ICJib3RoIikKc3RlcHdpc2VfbW9kZWwkYW5vdmEKYGBgCgpgYGB7ciBjcm9zcyB2YWxpZGF0aW9uLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nID0gRkFMU0V9CgpsbSA8LSAgdHJhaW5Db250cm9sKG1ldGhvZCA9ICJjdiIsIG51bWJlciA9IDUpCgpjdmxtX21vZGVsIDwtIHRyYWluKExOTUVESFZBTCB+IFBDVFZBQ0FOVCArIFBDVFNJTkdMRVMgKyBQQ1RCQUNITU9SICsgTE5OQkVMUE9WMTAwLCBkYXRhPWRhdGEsIG1ldGhvZCA9ICJsbSIsIHRyQ29udHJvbCA9IGxtKQoKcHJpbnQoY3ZsbV9tb2RlbCkKCmBgYAoKCmBgYHtyIHJlZHVjZSBjdiBtb2RlbCxtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKY3ZsbV9tb2RlbF9yZWR1Y2VkID0gdHJhaW4oTE5NRURIVkFMIH4gUENUVkFDQU5UICsgTUVESEhJTkMsIGRhdGEgPSBkYXRhLCBtZXRob2QgPSAibG0iLCB0ckNvbnRyb2wgPSBsbSkKCnByaW50KGN2bG1fbW9kZWxfcmVkdWNlZCkKYGBgCgoKIyBEaXNjdXNzaW9uCgpPdXIgcmVncmVzc2lvbiBhbmFseXNpcyBvZiBQaGlsYWRlbHBoaWHigJlzIGNlbnN1cyBibG9jayBncm91cCBkYXRhIGNsZWFybHkgc2hvd3MgaG93IG5laWdoYm9yaG9vZCBjaGFyYWN0ZXJpc3RpY3MgYWZmZWN0IGhvdXNpbmcgdmFsdWVzLiBPdXIgbW9kZWwgZXhwbGFpbnMgYWJvdXQgNjYlIG9mIHRoZSB2YXJpYXRpb24gaW4gdGhlIGxvZy10cmFuc2Zvcm1lZCBtZWRpYW4gaG91c2UgdmFsdWUgKExOTUVESFZBTCkuIFRoaXMgaW5kaWNhdGVzIHRoYXQgZmFjdG9ycyBzdWNoIGFzIHRoZSBwZXJjZW50YWdlIG9mIHZhY2FudCBob3VzZXMgKFBDVFZBQ0FOVCksIHRoZSBwZXJjZW50YWdlIG9mIHNpbmdsZS1mYW1pbHkgaG9tZXMgKFBDVFNJTkdMRVMpLCB0aGUgcGVyY2VudGFnZSBvZiByZXNpZGVudHMgd2l0aCBhdCBsZWFzdCBhIGJhY2hlbG9y4oCZcyBkZWdyZWUgKFBDVEJBQ0hNT1IpLCBhbmQgdGhlIGxvZy10cmFuc2Zvcm1lZCBudW1iZXIgb2YgaG91c2Vob2xkcyBsaXZpbmcgYmVsb3cgdGhlIHBvdmVydHkgbGluZSAoTE5OQkVMUE9WMTAwKSBhcmUgYWxsIGltcG9ydGFudCBpbiBzaGFwaW5nIGhvdXNpbmcgbWFya2V0IG91dGNvbWVzLgoKKipJbnRlcnByZXRpbmcgdGhlIFJlc3VsdHM6KioKCioqTmVlZCB0byByZXdyaXRlKiogV2UgY2Fubm90IGluY2x1ZGUgbG9nLXRyYW5zZm9ybWVkIHZhbHVlIGRpcmVjdGx5IGludG8gdGhlIHJlcG9ydCwgc2VlIHRoZSBhYm92ZSBpbnRlcnByZXQgc2VjdGlvbiBmb3IgdGhlIGludGVycHJldGF0aW9uIG9mIHRoZSByZXN1bHRzLgoKKipDaGVja2luZyB0aGUgTW9kZWwgQXNzdW1wdGlvbnM6KioKCioqYikJVGFsayBhYm91dCB0aGUgcXVhbGl0eSBvZiB0aGUgbW9kZWwg4oCTIHRoYXQgaXMsIHN0YXRlIGlmIHRoaXMgaXMgYSBnb29kIG1vZGVsIG92ZXJhbGwgKGUuZy4sIFIyLCBGLXJhdGlvIHRlc3QpLCBhbmQgd2hhdCBvdGhlciBwcmVkaWN0b3JzIHRoYXQgd2UgZGlkbuKAmXQgaW5jbHVkZSBpbiBvdXIgbW9kZWwgbWlnaHQgYmUgYXNzb2NpYXRlZCB3aXRoIG91ciBkZXBlbmRlbnQgdmFyaWFibGUuKioKaS4JTG9va2luZyBhdCB0aGUgc3RlcHdpc2UgcmVncmVzc2lvbiByZXN1bHRzLCBkaWQgdGhlIGZpbmFsIG1vZGVsIGluY2x1ZGUgYWxsIDQgcHJlZGljdG9ycyBvciB3ZXJlIHNvbWUgZHJvcHBlZD8gV2hhdCBkb2VzIHRoYXQgdGVsbCB5b3UgYWJvdXQgdGhlIHF1YWxpdHkgb2YgdGhlIG1vZGVsPyAKaWkuCUxvb2tpbmcgYXQgdGhlIGNyb3NzLXZhbGlkYXRpb24gcmVzdWx0cywgd2FzIHRoZSBSTVNFIGJldHRlciBmb3IgdGhlIDQgcHJlZGljdG9yIG1vZGVsIG9yIHRoZSAyIHByZWRpY3RvciBtb2RlbD8gIAoKCgpUbyB2YWxpZGF0ZSBvdXIgbW9kZWwsIHdlIHBlcmZvcm1lZCBzdGVwd2lzZSByZWdyZXNzaW9uIHVzaW5nIHRoZSBBa2Fpa2UgSW5mb3JtYXRpb24gQ3JpdGVyaW9uIChBSUMpIGFuZCBjb25kdWN0ZWQgNS1mb2xkIGNyb3NzLXZhbGlkYXRpb24uIFRoZSBzdGVwd2lzZSByZWdyZXNzaW9uIGNvbmZpcm1lZCB0aGF0IHRoZSBzZWxlY3RlZCBwcmVkaWN0b3JzIGNvbnRyaWJ1dGUgdG8gYSBzdHJvbmcgbW9kZWwgZml0LCB3aGlsZSB0aGUgY3Jvc3MtdmFsaWRhdGlvbiByZXN1bHRzIHNob3dlZCB0aGF0IHRoZSBmdWxsIG1vZGVsIHdoaWNoIGluY2x1ZGVzIGFsbCB0aGUgZm91ciBwcmVkaWN0b3JzIHBlcmZvcm1zIGJldHRlciB0aGFuIGEgcmVkdWNlZCBtb2RlbCB0aGF0IG9ubHkgaW5jbHVkZXMgdGhlIHBlcmNlbnRhZ2Ugb2YgdmFjYW50IGhvdXNlcyAoUENUVkFDQU5UKSBhbmQgbWVkaWFuIGhvdXNlaG9sZCBpbmNvbWUuIFRoZXNlIHJlc3VsdHMgc3RyZW5ndGhlbiBvdXIgY29uZmlkZW5jZSBpbiB0aGUgcHJlZGljdGl2ZSBwb3dlciBhbmQgcm9idXN0bmVzcyBvZiB0aGUgbW9kZWwuCgoKCioqUG9saWN5IEltcGxpY2F0aW9uczogQSBGb2N1cyBvbiBJbmNsdXNpdmUgR3Jvd3RoIGFuZCBTdGFiaWxpdHk6IChvbmUgcGFyYWdyYXBoIG9ubHkpKioKClRoZSBmaW5kaW5ncyBoYXZlIGltcG9ydGFudCBpbXBsaWNhdGlvbnMgZm9yIHVyYmFuIHBvbGljeSwgcGFydGljdWxhcmx5IGluIGVuc3VyaW5nIHRoYXQgc3RyYXRlZ2llcyB0byBpbXByb3ZlIGhvdXNpbmcgbWFya2V0cyBkbyBub3QgbGVhZCB0byBkaXNwbGFjZW1lbnQgb3IgaW5jcmVhc2VkIGhvdXNpbmcgYnVyZGVucyBmb3IgdnVsbmVyYWJsZSBjb21tdW5pdGllcy4gVGhlIHN0cm9uZyBuZWdhdGl2ZSBpbXBhY3Qgb2YgdmFjYW5jeSByYXRlcyAoUENUVkFDQU5UKSBvbiBob3VzaW5nIHZhbHVlcyBzdWdnZXN0cyB0aGF0IHJlZHVjaW5nIGxvbmctdGVybSB2YWNhbmNpZXMgY291bGQgcGxheSBhIHJvbGUgaW4gbmVpZ2hib3Job29kIHN0YWJpbGl6YXRpb24uIEhvd2V2ZXIsIHJhdGhlciB0aGFuIHBvbGljaWVzIHRoYXQgc29sZWx5IGZvY3VzIG9uIGluY3JlYXNpbmcgcHJvcGVydHkgdmFsdWVzLCBpbnRlcnZlbnRpb25zIHNob3VsZCBwcmlvcml0aXplIGVxdWl0YWJsZSBpbnZlc3RtZW50IGxpa2UgcmVoYWJpbGl0YXRpbmcgdmFjYW50IHByb3BlcnRpZXMgZm9yIGFmZm9yZGFibGUgaG91c2luZywgZXhwYW5kaW5nIGNvbW11bml0eSBsYW5kIHRydXN0cywgYW5kIG9mZmVyaW5nIHN1cHBvcnQgZm9yIGxvbmd0aW1lIHJlc2lkZW50cyBhdCByaXNrIG9mIGRpc3BsYWNlbWVudC4KClNpbWlsYXJseSwgdGhlIHN0cm9uZyByZWxhdGlvbnNoaXAgYmV0d2VlbiBlZHVjYXRpb25hbCBhdHRhaW5tZW50IChQQ1RCQUNITU9SKSBhbmQgaG91c2luZyB2YWx1ZXMgaGlnaGxpZ2h0cyB0aGUgaW1wb3J0YW5jZSBvZiBleHBhbmRpbmcgYWNjZXNzIHRvIGhpZ2gtcXVhbGl0eSBlZHVjYXRpb24gYW5kIHdvcmtmb3JjZSBkZXZlbG9wbWVudC4gSG93ZXZlciwgaW5jcmVhc2luZyBlZHVjYXRpb24gbGV2ZWxzIGFsb25lIGRvZXMgbm90IGVuc3VyZSBlcXVpdGFibGUgaG91c2luZyBvdXRjb21lcyBpZiBob3VzaW5nIGNvc3RzIHJpc2UgYmV5b25kIGFmZm9yZGFiaWxpdHkgZm9yIGV4aXN0aW5nIHJlc2lkZW50cy4gVGh1cywgcG9saWNpZXMgc2hvdWxkIGJlIGRlc2lnbmVkIHRvIGJhbGFuY2UgZWR1Y2F0aW9uYWwgaW52ZXN0bWVudCB3aXRoIGFmZm9yZGFiaWxpdHkgbWVhc3VyZXMsIHN1Y2ggYXMgcmVudGFsIGFzc2lzdGFuY2UgcHJvZ3JhbXMgYW5kIGZpcnN0LXRpbWUgaG9tZWJ1eWVyIHN1cHBvcnQgZm9yIGxvd2VyLWluY29tZSBob3VzZWhvbGRzLgoKVGhlIG5lZ2F0aXZlIGFzc29jaWF0aW9uIGJldHdlZW4gcG92ZXJ0eSBsZXZlbHMgKExOTkJFTFBPVjEwMCkgYW5kIGhvdXNpbmcgdmFsdWVzIGhpZ2hsaWdodHMgdGhlIG5lZWQgZm9yIGhvdXNpbmcgcG9saWNpZXMgdGhhdCBhY3RpdmVseSBjb21iYXQgZWNvbm9taWMgaW5lcXVhbGl0eSBhbmQgc3VwcG9ydCBhZmZvcmRhYmxlLCBzdGFibGUgY29tbXVuaXRpZXMuIFNvbHV0aW9ucyBzdWNoIGFzIG1peGVkLWluY29tZSBob3VzaW5nIGRldmVsb3BtZW50cywgaW5jb21lLWJhc2VkIHRheCBjcmVkaXRzLCBhbmQgZXhwYW5kZWQgdGVuYW50IHByb3RlY3Rpb25zIGNhbiBoZWxwIGVuc3VyZSB0aGF0IGVjb25vbWljIG1vYmlsaXR5IGRvZXMgbm90IGNvbWUgYXQgdGhlIGNvc3Qgb2YgZGlzcGxhY2VtZW50LiBUaGUgZ29hbCBzaG91bGQgYmUgdG8gY3JlYXRlIHN0YWJsZSwgbWl4ZWQtaW5jb21lIGNvbW11bml0aWVzIHdoZXJlIGVjb25vbWljIGdyb3d0aCBiZW5lZml0cyBib3RoIGN1cnJlbnQgcmVzaWRlbnRzIGFuZCBuZXcgYXJyaXZhbHMuCgoqKkxpbWl0YXRpb25zIGFuZCBGdXR1cmUgUmVzZWFyY2g6KioKCkFsdGhvdWdoIG91ciBtb2RlbCBwcm92aWRlcyBhIHN0cm9uZyB1bmRlcnN0YW5kaW5nIG9mIGhvdXNpbmcgbWFya2V0IGR5bmFtaWNzLCB0aGVyZSBhcmUgc2V2ZXJhbCBsaW1pdGF0aW9ucyB0aGF0IGZ1dHVyZSByZXNlYXJjaCBzaG91bGQgYWRkcmVzcy4gRmlyc3QsIHdoaWxlIG91ciBtb2RlbCBleHBsYWlucyBhIHNpZ25pZmljYW50IHBvcnRpb24gb2YgdGhlIHZhcmlhdGlvbiBpbiBob3VzaW5nIHZhbHVlcywgYWJvdXQgb25lLXRoaXJkIHJlbWFpbnMgdW5leHBsYWluZWQuIFRoaXMgc3VnZ2VzdHMgdGhhdCBvdGhlciBmYWN0b3JzIGxpa2UgYWNjZXNzIHRvIHRyYW5zcG9ydGF0aW9uLCBoaXN0b3JpY2FsIHJlZGxpbmluZyBwYXR0ZXJucywgb3IgdGhlIHByZXNlbmNlIG9mIHB1YmxpYyBhbWVuaXRpZXMgbWF5IHBsYXkgaW1wb3J0YW50IHJvbGVzIGFuZCBzaG91bGQgYmUgZXhwbG9yZWQgaW4gZnV0dXJlIHN0dWRpZXMuCgpUaGUgcG90ZW50aWFsIHByZXNlbmNlIG9mIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uIHN1Z2dlc3RzIHRoYXQgbmVpZ2hib3JpbmcgYmxvY2sgZ3JvdXBzIG1heSBub3QgYmUgZW50aXJlbHkgaW5kZXBlbmRlbnQsIHdoaWNoIGNvdWxkIGJpYXMgc29tZSBlc3RpbWF0ZXMuIEluY29ycG9yYXRpbmcgc3BhdGlhbCBlY29ub21ldHJpYyB0ZWNobmlxdWVzLCBzdWNoIGFzIHNwYXRpYWwgbGFnIG1vZGVscyBvciBnZW9ncmFwaGljYWxseSB3ZWlnaHRlZCByZWdyZXNzaW9uLCBjb3VsZCBpbXByb3ZlIHRoZSBhY2N1cmFjeSBvZiBmdXR1cmUgYW5hbHlzZXMuCgojIyMgUG9zc2liaWxpdHkgb2YgUmlkZ2Ugb3IgTEFTU08gUmVncmVzc2lvbgoKUmlkZ2UgYW5kIExBU1NPIHJlZ3Jlc3Npb24gYXJlIHVzZWQgd2hlbiB0aGVyZSBhcmUgaGlnaGx5IGNvcnJlbGF0ZWQgcHJlZGljdG9ycyBvciB3aGVuIG9ubHkgYSBzdWJzZXQgb2YgZmVhdHVyZXMgaXMgZXhwZWN0ZWQgdG8gYmUgdHJ1bHkgaW1wb3J0YW50LiBJbiBzdWNoIGNhc2VzLCBzb21lIHByZWRpY3RvciBjb2VmZmljaWVudHMgbWF5IGJlY29tZSBleGNlc3NpdmVseSBsYXJnZSwgbGVhZGluZyB0byBvdmVyZml0dGluZyBpbiBhIGxpbmVhciBtb2RlbC4gVGhlc2UgbWV0aG9kcyBtYW5hZ2Ugb3ZlcmZpdHRpbmcgYnkgYWRkaW5nIGEgcGVuYWx0eSB0ZXJtIHRvIHRoZSBsb3NzIGZ1bmN0aW9uLCB3aGljaCBjb25zdHJhaW5zIHRoZSBjb2VmZmljaWVudHMuIEhvd2V2ZXIsIGluIG91ciBtb2RlbCwgdGhlIGhpZ2hlc3QgY29ycmVsYXRpb24gYmV0d2VlbiBwcmVkaWN0b3JzIGlzIDAuMzIsIGluZGljYXRpbmcgbm8gc2lnbmlmaWNhbnQgbXVsdGljb2xsaW5lYXJpdHkuIEFkZGl0aW9uYWxseSwgbm8gcHJlZGljdG9yIGV4aGliaXRzIGV4Y2Vzc2l2ZWx5IGxhcmdlIGNvZWZmaWNpZW50cy4gVGhlcmVmb3JlLCBhcHBseWluZyBSaWRnZSBvciBMQVNTTyByZWdyZXNzaW9uIGluIHRoaXMgY2FzZSB3b3VsZCBiZSB1bm5lY2Vzc2FyeS4=